trie.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //
  2. // trie.hpp
  3. // trie
  4. //
  5. // Created by Sam Jaffe on 6/16/17.
  6. //
  7. #pragma once
  8. #include "pointers/const_propogating_ptr.hpp"
  9. #include "pointers/not_null.hpp"
  10. #include "pointers/value_ptr.hpp"
  11. #include <map>
  12. template <typename K, typename V, typename Compare = std::less<K>>
  13. class trie;
  14. namespace detail {
  15. template <typename Trie, typename Iter>
  16. class trie_iterator_base;
  17. }
  18. template <typename Trie, typename Iter>
  19. class trie_iterator;
  20. template <typename Trie, typename Iter>
  21. class trie_reverse_iterator;
  22. template <typename K, typename V, typename Compare>
  23. class trie {
  24. private:
  25. using self_t = trie<K, V, Compare>;
  26. using layer_t = value_ptr<self_t>;
  27. using backing_t = std::map<K, const_propogating_ptr<layer_t>, Compare>;
  28. template <typename KS>
  29. using is_collection_t = typename std::enable_if<std::is_same<K, std::decay_t<decltype(*std::begin(std::declval<KS>()))>>::value>::type;
  30. public:
  31. using key_type = K;
  32. using mapped_type = V;
  33. using key_compare = Compare;
  34. using local_iterator = typename backing_t::iterator;
  35. using local_const_iterator = typename backing_t::const_iterator;
  36. using local_reverse_iterator = typename backing_t::reverse_iterator;
  37. using local_const_reverse_iterator = typename backing_t::const_reverse_iterator;
  38. using iterator = trie_iterator<self_t, local_iterator>;
  39. using const_iterator = trie_iterator<self_t const, local_const_iterator>;
  40. using post_iterator = trie_iterator<self_t, local_reverse_iterator>;
  41. using const_post_iterator = trie_iterator<self_t const, local_const_reverse_iterator>;
  42. using reverse_iterator = trie_reverse_iterator<self_t, local_reverse_iterator>;
  43. using const_reverse_iterator = trie_reverse_iterator<self_t const, local_const_reverse_iterator>;
  44. private:
  45. using impl_iterator = detail::trie_iterator_base<self_t, local_iterator>;
  46. public:
  47. trie() {}
  48. trie(trie const & other);
  49. trie(trie && other) { swap(other); }
  50. ~trie() { clear(); }
  51. self_t & operator=(mapped_type const & value);
  52. self_t & operator=(trie const & value);
  53. self_t & operator=(trie && value);
  54. operator mapped_type &() { return value(); }
  55. operator mapped_type const &() const { return value(); }
  56. mapped_type & value() { return value_; }
  57. mapped_type const & value() const { return value_; }
  58. template <typename KS, typename = is_collection_t<KS>>
  59. self_t & operator[](KS const & keys) {
  60. return *emplace(keys).first.stk.top();
  61. }
  62. self_t & operator[](key_type const & key) {
  63. return *emplace(key).first.stk.top();
  64. }
  65. self_t & operator[](std::initializer_list<key_type> keys) {
  66. return operator[]<std::initializer_list<key_type>>(keys);
  67. }
  68. template <typename KS>
  69. std::pair<iterator, bool> insert(KS const & keys, mapped_type const & value) {
  70. return emplace_impl(keys, value);
  71. }
  72. std::pair<iterator, bool> insert(key_type const & key, mapped_type const & value) {
  73. return emplace_impl({key}, value);
  74. }
  75. std::pair<iterator, bool> insert(std::initializer_list<key_type> keys, mapped_type const & value) {
  76. return emplace_impl(keys, value);
  77. }
  78. template <typename KS, typename... Args>
  79. std::pair<iterator, bool> emplace(KS const & keys, Args &&... args) {
  80. return emplace_impl(keys, std::forward<Args>(args)...);
  81. }
  82. template <typename... Args>
  83. std::pair<iterator, bool> emplace(key_type const & key, Args &&... args) {
  84. return emplace_impl({key}, std::forward<Args>(args)...);
  85. }
  86. template <typename... Args>
  87. std::pair<iterator, bool> emplace(std::initializer_list<key_type> keys, Args &&... args) {
  88. return emplace_impl(keys, std::forward<Args>(args)...);
  89. }
  90. iterator begin() { return {this}; }
  91. iterator end() { return {}; }
  92. const_iterator begin() const { return {this}; }
  93. const_iterator end() const { return {}; }
  94. const_iterator cbegin() const { return begin(); }
  95. const_iterator cend() const { return end(); }
  96. reverse_iterator rbegin() { return {this}; }
  97. reverse_iterator rend() { return {}; }
  98. const_reverse_iterator rbegin() const { return {this}; }
  99. const_reverse_iterator rend() const { return {}; }
  100. const_reverse_iterator crbegin() const { return rbegin(); }
  101. const_reverse_iterator crend() const { return rend(); }
  102. local_iterator local_begin() { return impl_.begin(); }
  103. local_iterator local_end() { return impl_.end(); }
  104. local_const_iterator local_begin() const { return impl_.begin(); }
  105. local_const_iterator local_end() const { return impl_.end(); }
  106. local_reverse_iterator local_rbegin() { return impl_.rbegin(); }
  107. local_reverse_iterator local_rend() { return impl_.rend(); }
  108. local_const_reverse_iterator local_rbegin() const { return impl_.rbegin(); }
  109. local_const_reverse_iterator local_rend() const { return impl_.rend(); }
  110. template <typename KS>
  111. iterator find(KS const & keys) { return find_impl(keys); }
  112. iterator find(key_type const & key) { return find_impl({key}); }
  113. iterator find(std::initializer_list<key_type> keys) { return find_impl(keys); }
  114. template <typename KS>
  115. void erase(KS const & keys) { drop(find(keys)); }
  116. void erase(key_type const & key) { drop(find(key)); }
  117. void erase(std::initializer_list<key_type> keys) { drop(find(keys)); }
  118. void clear();
  119. private:
  120. void drop(iterator it);
  121. template <typename KS>
  122. impl_iterator find_impl(KS const & keys);
  123. impl_iterator find_impl(std::initializer_list<key_type> keys) {
  124. return find_impl<std::initializer_list<key_type>>(keys);
  125. }
  126. template <typename KS, typename... Args>
  127. std::pair<impl_iterator, bool> emplace_impl(KS const & keys, Args &&... args);
  128. template <typename... Args>
  129. std::pair<impl_iterator, bool> emplace_impl(std::initializer_list<key_type> key, Args &&... args) {
  130. return emplace_impl<std::initializer_list<key_type>>(key, std::forward<Args>(args)...);
  131. }
  132. void insert_impl(impl_iterator & out, bool & create, key_type const & key);
  133. friend bool operator==(trie const & lhs, trie const & rhs) {
  134. auto it1 = lhs.begin(), it2 = rhs.begin(), end1 = lhs.end(), end2 = lhs.end();
  135. for ( ; it1 != end1 && it2 != end2; ++it1, ++it2 ) {
  136. if (!it1.keys.empty() && !it2.keys.empty() && it1.keys.back() != it2.keys.back()) { return false; }
  137. else if (it1.stk.top()->value_ != it2.stk.top()->value_) { return false; }
  138. }
  139. return it1 == end1 && it2 == end2;
  140. }
  141. friend void swap(trie & lhs, trie & rhs) {
  142. using std::swap;
  143. swap(lhs.value_, rhs.value_);
  144. swap(lhs.impl_, rhs.impl_);
  145. }
  146. mapped_type value_{};
  147. backing_t impl_{};
  148. };
  149. #include "trie_impl.hpp"