1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 * A sorted tree with optimal access times, where recently-accessed elements
9 * are faster to access again.
12 #ifndef mozilla_SplayTree_h
13 #define mozilla_SplayTree_h
15 #include "mozilla/Assertions.h"
16 #include "mozilla/NullPtr.h"
20 template<class T
, class C
>
27 template<class A
, class B
>
28 friend class SplayTree
;
31 : left(nullptr), right(nullptr), parent(nullptr)
42 * Class which represents a splay tree.
43 * Splay trees are balanced binary search trees for which search, insert and
44 * remove are all amortized O(log n), but where accessing a node makes it
45 * faster to access that node in the future.
47 * T indicates the type of tree elements, Comparator must have a static
48 * compare(const T&, const T&) method ordering the elements. The compare
49 * method must be free from side effects.
51 template<typename T
, class Comparator
>
59 : root(nullptr), freeList(nullptr)
66 bool contains(const T
& v
)
73 checkCoherency(root
, nullptr);
74 return Comparator::compare(v
, *last
) == 0;
79 MOZ_ASSERT(!contains(*v
), "Duplicate elements are not allowed.");
86 int cmp
= Comparator::compare(*v
, *last
);
88 T
** parentPointer
= (cmp
< 0) ? &last
->left
: &last
->right
;
89 MOZ_ASSERT(!*parentPointer
);
94 checkCoherency(root
, nullptr);
101 MOZ_ASSERT(last
, "This tree must contain the element being removed.");
102 MOZ_ASSERT(Comparator::compare(v
, *last
) == 0);
104 // Splay the tree so that the item to remove is the root.
106 MOZ_ASSERT(last
== root
);
108 // Find another node which can be swapped in for the root: either the
109 // rightmost child of the root's left, or the leftmost child of the
117 swapChild
= swap
->left
;
118 } else if (root
->right
) {
122 swapChild
= swap
->right
;
129 // The selected node has at most one child, in swapChild. Detach it
130 // from the subtree by replacing it with that child.
131 if (swap
== swap
->parent
->left
)
132 swap
->parent
->left
= swapChild
;
134 swap
->parent
->right
= swapChild
;
136 swapChild
->parent
= swap
->parent
;
138 // Make the selected node the new root.
140 root
->parent
= nullptr;
141 root
->left
= last
->left
;
142 root
->right
= last
->right
;
144 root
->left
->parent
= root
;
147 root
->right
->parent
= root
;
150 checkCoherency(root
, nullptr);
156 MOZ_ASSERT(root
, "No min to remove!");
166 * Returns the node in this comparing equal to |v|, or a node just greater or
167 * just less than |v| if there is no such node.
169 T
* lookup(const T
& v
)
171 MOZ_ASSERT(!empty());
177 int c
= Comparator::compare(v
, *node
);
189 * Rotate the tree until |node| is at the root of the tree. Performing
190 * the rotations in this fashion preserves the amortized balancing of
197 while (node
!= root
) {
198 T
* parent
= node
->parent
;
199 if (parent
== root
) {
202 MOZ_ASSERT(node
== root
);
205 T
* grandparent
= parent
->parent
;
206 if ((parent
->left
== node
) == (grandparent
->left
== parent
)) {
220 // Rearrange nodes so that node becomes the parent of its current
221 // parent, while preserving the sortedness of the tree.
222 T
* parent
= node
->parent
;
223 if (parent
->left
== node
) {
227 parent
->left
= node
->right
;
229 node
->right
->parent
= parent
;
230 node
->right
= parent
;
232 MOZ_ASSERT(parent
->right
== node
);
236 parent
->right
= node
->left
;
238 node
->left
->parent
= parent
;
241 node
->parent
= parent
->parent
;
242 parent
->parent
= node
;
243 if (T
* grandparent
= node
->parent
) {
244 if (grandparent
->left
== parent
)
245 grandparent
->left
= node
;
247 grandparent
->right
= node
;
253 T
* checkCoherency(T
* node
, T
* minimum
)
256 MOZ_ASSERT_IF(root
, !root
->parent
);
261 MOZ_ASSERT_IF(!node
->parent
, node
== root
);
262 MOZ_ASSERT_IF(minimum
, Comparator::compare(*minimum
, *node
) < 0);
264 MOZ_ASSERT(node
->left
->parent
== node
);
265 T
* leftMaximum
= checkCoherency(node
->left
, minimum
);
266 MOZ_ASSERT(Comparator::compare(*leftMaximum
, *node
) < 0);
269 MOZ_ASSERT(node
->right
->parent
== node
);
270 return checkCoherency(node
->right
, node
);
278 SplayTree(const SplayTree
&) MOZ_DELETE
;
279 void operator=(const SplayTree
&) MOZ_DELETE
;
282 } /* namespace mozilla */
284 #endif /* mozilla_SplayTree_h */