/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** * A sorted tree with optimal access times, where recently-accessed elements * are faster to access again.
*/
/** * Class which represents a splay tree. * Splay trees are balanced binary search trees for which search, insert and * remove are all amortized O(log n), but where accessing a node makes it * faster to access that node in the future. * * T indicates the type of tree elements, Comparator must have a static * compare(const T&, const T&) method ordering the elements. The compare * method must be free from side effects.
*/ template <typename T, class Comparator> class SplayTree {
T* mRoot;
T* last = lookup(aValue);
splay(last); return Comparator::compare(aValue, *last) == 0 ? last : nullptr;
}
void insert(T* aValue) {
MOZ_ASSERT(!find(*aValue), "Duplicate elements are not allowed.");
if (!mRoot) {
mRoot = aValue; return;
}
T* last = lookup(*aValue); int cmp = Comparator::compare(*aValue, *last);
finishInsertion(last, cmp, aValue);
}
T* findOrInsert(const T& aValue);
T* remove(const T& aValue) {
T* last = lookup(aValue);
MOZ_ASSERT(last, "This tree must contain the element being removed.");
MOZ_ASSERT(Comparator::compare(aValue, *last) == 0);
// Splay the tree so that the item to remove is the root.
splay(last);
MOZ_ASSERT(last == mRoot);
// Find another node which can be swapped in for the root: either the // rightmost child of the root's left, or the leftmost child of the // root's right.
T* swap;
T* swapChild; if (mRoot->mLeft) {
swap = mRoot->mLeft; while (swap->mRight) {
swap = swap->mRight;
}
swapChild = swap->mLeft;
} elseif (mRoot->mRight) {
swap = mRoot->mRight; while (swap->mLeft) {
swap = swap->mLeft;
}
swapChild = swap->mRight;
} else {
T* result = mRoot;
mRoot = nullptr; return result;
}
// The selected node has at most one child, in swapChild. Detach it // from the subtree by replacing it with that child. if (swap == swap->mParent->mLeft) {
swap->mParent->mLeft = swapChild;
} else {
swap->mParent->mRight = swapChild;
} if (swapChild) {
swapChild->mParent = swap->mParent;
}
// Make the selected node the new root.
mRoot = swap;
mRoot->mParent = nullptr;
mRoot->mLeft = last->mLeft;
mRoot->mRight = last->mRight; if (mRoot->mLeft) {
mRoot->mLeft->mParent = mRoot;
} if (mRoot->mRight) {
mRoot->mRight->mParent = mRoot;
}
private: /** * Returns the node in this comparing equal to |aValue|, or a node just * greater or just less than |aValue| if there is no such node.
*/
T* lookup(const T& aValue) {
MOZ_ASSERT(!empty());
T* node = mRoot;
T* parent; do {
parent = node; int c = Comparator::compare(aValue, *node); if (c == 0) { return node;
} elseif (c < 0) {
node = node->mLeft;
} else {
node = node->mRight;
}
} while (node); return parent;
}
/** * Rotate the tree until |node| is at the root of the tree. Performing * the rotations in this fashion preserves the amortized balancing of * the tree.
*/ void splay(T* aNode) {
MOZ_ASSERT(aNode);
void rotate(T* aNode) { // Rearrange nodes so that aNode becomes the parent of its current // parent, while preserving the sortedness of the tree.
T* parent = aNode->mParent; if (parent->mLeft == aNode) { // x y // y c ==> a x // a b b c
parent->mLeft = aNode->mRight; if (aNode->mRight) {
aNode->mRight->mParent = parent;
}
aNode->mRight = parent;
} else {
MOZ_ASSERT(parent->mRight == aNode); // x y // a y ==> x c // b c a b
parent->mRight = aNode->mLeft; if (aNode->mLeft) {
aNode->mLeft->mParent = parent;
}
aNode->mLeft = parent;
}
aNode->mParent = parent->mParent;
parent->mParent = aNode; if (T* grandparent = aNode->mParent) { if (grandparent->mLeft == parent) {
grandparent->mLeft = aNode;
} else {
grandparent->mRight = aNode;
}
} else {
mRoot = aNode;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.