// // trie_impl.hpp // trie // // Created by Sam Jaffe on 6/16/17. // #pragma once #include "trie.hpp" #include "trie_iterator.hpp" template trie::trie(mapped_type const & value) : value_(value) { } // n := total elements // d := average depth // Stack: O(1) // Operations: O(n*d) template trie::trie(trie const & other) { for (const_iterator it = other.begin(), end = other.end(); it != end; ++it) { insert(it.keys, *it); } } template trie::~trie() { clear(); } template auto trie::operator=(mapped_type const & value) -> self_t & { value_ = value; return *this; } template auto trie::operator=(trie const & other) -> self_t & { trie tmp{other}; swap(*this, tmp); return *this; } // n := total elements // d := average depth // Operations: O(d*log(n/d)) template template auto trie::operator[](KS const & keys) -> self_t & { self_t * rec = this; for ( key_type const & key : keys ) { rec = &(*rec)[key]; } return *rec; } // n := total elements // d := average depth // Operations: O(log(n)) template auto trie::operator[](key_type const & key) -> self_t & { auto it = impl_.lower_bound(key); if ( it == impl_.end() || key_compare()(key, it->first) ) { it = impl_.emplace_hint(it, key, make_value()); } return *(it->second); } // n := total elements // d := average depth // Operations: O(d*log(n/d)) template auto trie::operator[](std::initializer_list keys) -> self_t & { self_t * rec = this; for ( key_type const & key : keys ) { rec = &(*rec)[key]; } return *rec; } template template auto trie::insert(KS const & keys, mapped_type const & value) -> void { operator[](keys) = value; } template auto trie::insert(std::initializer_list keys, mapped_type const & value) -> void { operator[](keys) = value; } template auto trie::insert(key_type const & key, mapped_type const & value) -> std::pair { auto it = impl_.lower_bound(key); if ( it == impl_.end() || key_compare()(key, it->first) ) { return { impl_.emplace_hint(it, key, make_value(value)), true }; // n := total elements // d := average depth // Stack: O(1) // Operations: O(n) template void trie::clear() { for (reverse_iterator it = rbegin(), end = rend(); it != end && !it.iters.empty(); ++it) { auto ptr = std::move(it.iters.top()->second); ptr->impl_.clear(); } value_ = mapped_type{}; impl_.clear(); }