// // trie_impl.hpp // trie // // Created by Sam Jaffe on 6/16/17. // #pragma once #include "trie.hpp" #include "trie_iterator.hpp" // n := total elements // d := average depth // Stack: O(1) // Operations: O(n) template trie::trie(trie const & other) : value_(other.value_) { impl_iterator current{this}; for (const_iterator it = ++other.begin(), end = {}; it != end; ++it) { while (current.keys_.size() >= it.keys_.size()) { current.pop(); } auto tmp = current.root().insert(it.keys_.back(), *it).first; current.push(tmp.current()); } } template trie::trie(mapped_type const & root, std::map && children) : value_(root) { for (auto & pair : children) { operator[](pair.first) = std::move(pair.second); } } template auto trie::operator=(mapped_type const & value) -> trie & { value_ = value; return *this; } template auto trie::operator=(trie const & other) -> trie & { trie tmp{other}; swap(*this, tmp); return *this; } template auto trie::operator=(trie && other) -> trie & { swap(*this, other); return *this; } // n := total elements // d := average depth // Operations: O(log(n)/d) template template void trie::insert_impl(impl_iterator & out, bool & create, Key && key) { auto it = impl_.lower_bound(key); if (it == impl_.end() || key_compare()(key, it->first)) { create = true; it = impl_.emplace_hint(it, key, make_value()); } out.push({it, impl_.end()}); } // n := total elements // d := average depth // Operations: O(log(n)) template template auto trie::emplace_impl(KS && keys, Args &&... args) -> std::pair { impl_iterator it{this}; bool create{false}; for (auto && key : keys) { it.root().insert_impl(it, create, std::forward(key)); } if (create) { it.root().value_ = {std::forward(args)...}; } return {std::move(it), create}; } // 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.empty(); ++it) { auto ptr = std::move(it.current()->second); ptr->impl_.clear(); } value_ = mapped_type{}; impl_.clear(); } template void trie::drop(iterator it) { if (it == end()) return; it.root().clear(); if (!it.empty()) { auto to_erase = it.current().current(); it.pop(); it.root().impl_.erase(to_erase); } } namespace detail { template Iter find_impl(Trie * tr, KS const & keys) { Iter rval{tr}; for (auto & key : keys) { auto & top = rval.root().impl_; auto it = top.find(key), end = top.end(); if (it == end) { return {}; } rval.push({it, end}); } return rval; } }