bug 606080 - add SplayTree::LookupOrAdd r=froydnj

This commit is contained in:
Trevor Saunders 2015-04-28 15:55:29 -04:00
parent 79b41494fa
commit 46d0164fdd
2 changed files with 81 additions and 8 deletions

View File

@ -13,6 +13,7 @@
#define mozilla_SplayTree_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
namespace mozilla {
@ -55,7 +56,7 @@ class SplayTree
T* mRoot;
public:
SplayTree()
MOZ_CONSTEXPR SplayTree()
: mRoot(nullptr)
{}
@ -86,15 +87,12 @@ public:
T* last = lookup(*aValue);
int cmp = Comparator::compare(*aValue, *last);
T** parentPointer = (cmp < 0) ? &last->mLeft : &last->mRight;
MOZ_ASSERT(!*parentPointer);
*parentPointer = aValue;
aValue->mParent = last;
splay(aValue);
finishInsertion(last, cmp, aValue);
return true;
}
T* findOrInsert(const T& aValue);
T* remove(const T& aValue)
{
T* last = lookup(aValue);
@ -196,6 +194,19 @@ private:
return parent;
}
T* finishInsertion(T* aLast, int32_t aCmp, T* aNew)
{
MOZ_ASSERT(aCmp, "Nodes shouldn't be equal!");
T** parentPointer = (aCmp < 0) ? &aLast->mLeft : &aLast->mRight;
MOZ_ASSERT(!*parentPointer);
*parentPointer = aNew;
aNew->mParent = aLast;
splay(aNew);
return aNew;
}
/**
* Rotate the tree until |node| is at the root of the tree. Performing
* the rotations in this fashion preserves the amortized balancing of
@ -295,6 +306,24 @@ private:
void operator=(const SplayTree&) = delete;
};
template<typename T, class Comparator>
T*
SplayTree<T, Comparator>::findOrInsert(const T& aValue)
{
if (!mRoot) {
mRoot = new T(aValue);
return mRoot;
}
T* last = lookup(aValue);
int cmp = Comparator::compare(aValue, *last);
if (!cmp) {
return last;
}
return finishInsertion(last, cmp, new T(aValue));
}
} /* namespace mozilla */
#endif /* mozilla_SplayTree_h */

View File

@ -105,6 +105,16 @@ struct SplayInt : SplayTreeNode<SplayInt>
int mValue;
};
struct SplayNoCopy : SplayTreeNode<SplayNoCopy>
{
SplayNoCopy(const SplayNoCopy&) = delete;
SplayNoCopy(SplayNoCopy&&) = delete;
static int compare(const SplayNoCopy&, const SplayNoCopy&) {}
};
static SplayTree<SplayNoCopy, SplayNoCopy> testNoCopy;
int
main()
{
@ -119,13 +129,47 @@ main()
// Insert the values, and check each one is findable just after insertion.
for (int i = 0; i < N; i++) {
tree.insert(new SplayInt(gValues[i]));
MOZ_RELEASE_ASSERT(tree.find(SplayInt(gValues[i])));
SplayInt* inserted = tree.find(SplayInt(gValues[i]));
MOZ_RELEASE_ASSERT(inserted);
MOZ_RELEASE_ASSERT(tree.findOrInsert(SplayInt(gValues[i])) == inserted);
tree.checkCoherency();
}
// Check they're all findable after all insertions.
for (int i = 0; i < N; i++) {
MOZ_RELEASE_ASSERT(tree.find(SplayInt(gValues[i])));
MOZ_RELEASE_ASSERT(tree.findOrInsert(SplayInt(gValues[i])));
tree.checkCoherency();
}
// Check that non-inserted values cannot be found.
MOZ_RELEASE_ASSERT(!tree.find(SplayInt(-1)));
MOZ_RELEASE_ASSERT(!tree.find(SplayInt(N)));
MOZ_RELEASE_ASSERT(!tree.find(SplayInt(0x7fffffff)));
// Remove the values, and check each one is not findable just after removal.
for (int i = 0; i < N; i++) {
SplayInt* removed = tree.remove(SplayInt(gValues[i]));
MOZ_RELEASE_ASSERT(removed->mValue == gValues[i]);
MOZ_RELEASE_ASSERT(!tree.find(*removed));
delete removed;
tree.checkCoherency();
}
MOZ_RELEASE_ASSERT(tree.empty());
// Insert the values, and check each one is findable just after insertion.
for (int i = 0; i < N; i++) {
SplayInt* inserted = tree.findOrInsert(SplayInt(gValues[i]));
MOZ_RELEASE_ASSERT(tree.find(SplayInt(gValues[i])) == inserted);
MOZ_RELEASE_ASSERT(tree.findOrInsert(SplayInt(gValues[i])) == inserted);
tree.checkCoherency();
}
// Check they're all findable after all insertions.
for (int i = 0; i < N; i++) {
MOZ_RELEASE_ASSERT(tree.find(SplayInt(gValues[i])));
MOZ_RELEASE_ASSERT(tree.findOrInsert(SplayInt(gValues[i])));
tree.checkCoherency();
}