1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=99 ft=cpp:
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 * A sorted tree with optimal access times, where recently-accessed elements
10 * are faster to access again.
13 #ifndef mozilla_SplayTree_h_
14 #define mozilla_SplayTree_h_
16 #include "mozilla/Assertions.h"
17 #include "mozilla/NullPtr.h"
21 template<class T
, class C
>
28 template<class A
, class B
>
29 friend class SplayTree
;
32 : left(nullptr), right(nullptr), parent(nullptr)
43 * Class which represents a splay tree.
44 * Splay trees are balanced binary search trees for which search, insert and
45 * remove are all amortized O(log n), but where accessing a node makes it
46 * faster to access that node in the future.
48 * T indicates the type of tree elements, Comparator must have a static
49 * compare(const T&, const T&) method ordering the elements. The compare
50 * method must be free from side effects.
52 template<typename T
, class Comparator
>
60 : root(nullptr), freeList(nullptr)
67 bool contains(const T
& v
)
74 checkCoherency(root
, nullptr);
75 return Comparator::compare(v
, *last
) == 0;
80 MOZ_ASSERT(!contains(*v
), "Duplicate elements are not allowed.");
87 int cmp
= Comparator::compare(*v
, *last
);
89 T
** parentPointer
= (cmp
< 0) ? &last
->left
: &last
->right
;
90 MOZ_ASSERT(!*parentPointer
);
95 checkCoherency(root
, nullptr);
102 MOZ_ASSERT(last
, "This tree must contain the element being removed.");
103 MOZ_ASSERT(Comparator::compare(v
, *last
) == 0);
105 // Splay the tree so that the item to remove is the root.
107 MOZ_ASSERT(last
== root
);
109 // Find another node which can be swapped in for the root: either the
110 // rightmost child of the root's left, or the leftmost child of the
118 swapChild
= swap
->left
;
119 } else if (root
->right
) {
123 swapChild
= swap
->right
;
130 // The selected node has at most one child, in swapChild. Detach it
131 // from the subtree by replacing it with that child.
132 if (swap
== swap
->parent
->left
)
133 swap
->parent
->left
= swapChild
;
135 swap
->parent
->right
= swapChild
;
137 swapChild
->parent
= swap
->parent
;
139 // Make the selected node the new root.
141 root
->parent
= nullptr;
142 root
->left
= last
->left
;
143 root
->right
= last
->right
;
145 root
->left
->parent
= root
;
148 root
->right
->parent
= root
;
151 checkCoherency(root
, nullptr);
157 MOZ_ASSERT(root
, "No min to remove!");
167 * Returns the node in this comparing equal to |v|, or a node just greater or
168 * just less than |v| if there is no such node.
170 T
* lookup(const T
& v
)
172 MOZ_ASSERT(!empty());
178 int c
= Comparator::compare(v
, *node
);
190 * Rotate the tree until |node| is at the root of the tree. Performing
191 * the rotations in this fashion preserves the amortized balancing of
198 while (node
!= root
) {
199 T
* parent
= node
->parent
;
200 if (parent
== root
) {
203 MOZ_ASSERT(node
== root
);
206 T
* grandparent
= parent
->parent
;
207 if ((parent
->left
== node
) == (grandparent
->left
== parent
)) {
221 // Rearrange nodes so that node becomes the parent of its current
222 // parent, while preserving the sortedness of the tree.
223 T
* parent
= node
->parent
;
224 if (parent
->left
== node
) {
228 parent
->left
= node
->right
;
230 node
->right
->parent
= parent
;
231 node
->right
= parent
;
233 MOZ_ASSERT(parent
->right
== node
);
237 parent
->right
= node
->left
;
239 node
->left
->parent
= parent
;
242 node
->parent
= parent
->parent
;
243 parent
->parent
= node
;
244 if (T
* grandparent
= node
->parent
) {
245 if (grandparent
->left
== parent
)
246 grandparent
->left
= node
;
248 grandparent
->right
= node
;
254 T
* checkCoherency(T
* node
, T
* minimum
)
257 MOZ_ASSERT_IF(root
, !root
->parent
);
262 MOZ_ASSERT_IF(!node
->parent
, node
== root
);
263 MOZ_ASSERT_IF(minimum
, Comparator::compare(*minimum
, *node
) < 0);
265 MOZ_ASSERT(node
->left
->parent
== node
);
266 T
* leftMaximum
= checkCoherency(node
->left
, minimum
);
267 MOZ_ASSERT(Comparator::compare(*leftMaximum
, *node
) < 0);
270 MOZ_ASSERT(node
->right
->parent
== node
);
271 return checkCoherency(node
->right
, node
);
279 SplayTree(const SplayTree
&) MOZ_DELETE
;
280 void operator=(const SplayTree
&) MOZ_DELETE
;
283 } /* namespace mozilla */
285 #endif /* mozilla_SplayTree_h_ */