Преглед на файлове

Fixing insert(key_type const &, mapped_type const &) to properly return iterator.

Samuel Jaffe преди 8 години
родител
ревизия
b1f756b780
променени са 3 файла, в които са добавени 56 реда и са изтрити 36 реда
  1. 32 18
      trie.t.h
  2. 10 1
      trie_impl.hpp
  3. 14 17
      trie_iterator.hpp

+ 32 - 18
trie.t.h

@@ -22,33 +22,32 @@ private:
     data[1] = 2;
     data[{0, 1}] = 4;
   }
+  
+  template <typename Iter, typename R>
+  static void container_equals(Iter l_it, R const & rhs) {
+    decltype(l_it) l_end{};
+    auto r_it = std::begin(rhs), r_end = std::end(rhs);
+    auto l_size = std::distance(l_it, l_end), r_size = std::distance(r_it, r_end);
+    TS_ASSERT_EQUALS(l_size, r_size);
+    for ( ; l_it != l_end && r_it != r_end; ++l_it, ++r_it ) {
+      TS_ASSERT_EQUALS(*l_it, *r_it);
+    }
+  }
 public:
   void testIterationIsPreOrder() {
-    auto it = data.cbegin();
-    TS_ASSERT_EQUALS(*it, -1);
-    TS_ASSERT_EQUALS(*++it, 5);
-    TS_ASSERT_EQUALS(*++it, 4);
-    TS_ASSERT_EQUALS(*++it, 2);
-    TS_ASSERT_EQUALS(++it, data.cend());
+    int const expected[] = { -1, 5, 4, 2 };
+    container_equals(data.begin(), expected);
   }
   
   void testPostIterationIsPostOrder() {
+    int const expected[] = { -1, 2, 5, 4 };
     auto it = trie<int, int>::const_post_iterator{&data};
-    decltype(it) end{};
-    TS_ASSERT_EQUALS(*it, -1);
-    TS_ASSERT_EQUALS(*++it, 2);
-    TS_ASSERT_EQUALS(*++it, 5);
-    TS_ASSERT_EQUALS(*++it, 4);
-    TS_ASSERT_EQUALS(++it, end);
+    container_equals(it, expected);
   }
 
   void testReverseIterationIsInvDepthFirst() {
-    auto it = data.crbegin();
-    TS_ASSERT_EQUALS(*it, 2);
-    TS_ASSERT_EQUALS(*++it, 4);
-    TS_ASSERT_EQUALS(*++it, 5);
-    TS_ASSERT_EQUALS(*++it, -1);
-    TS_ASSERT_EQUALS(++it, data.crend());
+    int const expected[] = { 2, 4, 5, -1 };
+    container_equals(data.crbegin(), expected);
   }
 
   void testCopyCtorIsDeepCopy() {
@@ -57,4 +56,19 @@ public:
     copy[{0, 1}] = 3;
     TS_ASSERT_DIFFERS(data, copy);
   }
+  
+  void testInsertNewElementOutputsTrue() {
+    trie<int, int> test;
+    auto pair = test.insert(1, 2);
+    TS_ASSERT_EQUALS(*pair.first, 2);
+    TS_ASSERT(pair.second);
+  }
+
+  void testInsertNotDestructive() {
+    trie<int, int> test;
+    auto pair = test.insert(1, 2);
+    pair = test.insert(1, 0);
+    TS_ASSERT_EQUALS(*pair.first, 2);
+    TS_ASSERT(!pair.second);
+  }
 };

+ 10 - 1
trie_impl.hpp

@@ -93,11 +93,20 @@ auto trie<K, V, C>::insert(std::initializer_list<key_type> keys, mapped_type con
   operator[](keys) = value;
 }
 
+// n := total elements
+// d := average depth
+// Operations: O(log(n))
 template <typename K, typename V, typename C>
 auto trie<K, V, C>::insert(key_type const & key, mapped_type const & value) -> std::pair<iterator, bool> {
+  std::pair<iterator, bool> rval{this, false};
   auto it = impl_.lower_bound(key);
   if ( it == impl_.end() || key_compare()(key, it->first) ) {
-    return { impl_.emplace_hint(it, key, make_value<self_t>(value)), true };
+    rval.second = true;
+    it = impl_.emplace_hint(it, key, make_value<self_t>(value));
+  }
+  rval.first.push(make_end_aware_iterator(it, impl_.end()));
+  return rval;
+}
 
 // n := total elements
 // d := average depth

+ 14 - 17
trie_iterator.hpp

@@ -42,28 +42,25 @@ namespace detail {
     trie_iterator_base(Trie * tr) { stk.push(tr); }
     auto operator*() const -> decltype(this->stk.top()->value()) { return *stk.top(); }
   protected:
+    void push(impl_t it) {
+      iters.push(it);
+      keys.push_back(it->first);
+      stk.push(it->second.get());
+    }
     bool poping_empty() {
-      if (iters.top().done()) {
-        stk.pop();
-        iters.pop();
-        keys.pop_back();
-        return !iters.empty();
-      }
-      return false;
+      if (!iters.top().done()) { return false; }
+      stk.pop();
+      iters.pop();
+      keys.pop_back();
+      return !iters.empty();
     }
     void assign() {
-      if (!iters.empty()) {
-        stk.top() = iters.top()->second.get();
-        keys.back() = iters.top()->first;
-      }
+      if (iters.empty()) { return; }
+      stk.top() = iters.top()->second.get();
+      keys.back() = iters.top()->first;
     }
     bool can_recurse() { return !next().done(); }
-    void recurse() {
-      auto it = next();
-      iters.push(it);
-      keys.push_back(it->first);
-      stk.push(it->second.get());
-    }
+    void recurse() { push(next()); }
     impl_t next() { return detail::trie_iterator_next<Iter>()(*stk.top()); }
     friend bool operator!=(trie_iterator_base const & lhs, trie_iterator_base const & rhs) {
       return !(lhs == rhs);