Avl Test case passed
This commit is contained in:
parent
2c94e02260
commit
88511539ac
3 changed files with 129 additions and 9 deletions
|
|
@ -16,9 +16,9 @@ namespace tp {
|
|||
inline bool descentLeft(AvlNumericKey in) const { return in.val < val; }
|
||||
inline bool exactNode(AvlNumericKey in) const { return in.val == val; }
|
||||
|
||||
inline AvlNumericKey getFindKey(/**/) const { return val; }
|
||||
inline AvlNumericKey keyInRightSubtree(AvlNumericKey in) const { return in.val; }
|
||||
inline AvlNumericKey keyInLeftSubtree(AvlNumericKey in) const { return in.val; }
|
||||
inline AvlNumericKey getFindKey(/**/) const { return *this; }
|
||||
inline AvlNumericKey keyInRightSubtree(AvlNumericKey in) const { return in; }
|
||||
inline AvlNumericKey keyInLeftSubtree(AvlNumericKey in) const { return in; }
|
||||
|
||||
inline void updateTreeCacheCallBack() {}
|
||||
};
|
||||
|
|
@ -47,7 +47,7 @@ namespace tp {
|
|||
|
||||
private:
|
||||
inline bool descentRight(KeyArg aKey) const { return key.descentRight(aKey); }
|
||||
inline bool descentLeft(KeyArg aKey) const { return key.descentRight(aKey); }
|
||||
inline bool descentLeft(KeyArg aKey) const { return key.descentLeft(aKey); }
|
||||
inline bool exactNode(KeyArg aKey) const { return key.exactNode(aKey); }
|
||||
|
||||
inline KeyArg getFindKey(const Node* node = nullptr) const { return key.getFindKey(/*node*/); }
|
||||
|
|
@ -73,7 +73,13 @@ namespace tp {
|
|||
return new (mAlloc.allocate(sizeof(Node))) Node(key, data);
|
||||
}
|
||||
|
||||
inline ualni getNodeHeight(const Node* node) const {
|
||||
inline void injectNodeInstead(Node* place, Node* inject) {
|
||||
// TODO : swap instead of copy
|
||||
place->data = inject->data;
|
||||
place->key = inject->key;
|
||||
}
|
||||
|
||||
inline alni getNodeHeight(const Node* node) const {
|
||||
return node ? node->mHeight : -1;
|
||||
}
|
||||
|
||||
|
|
@ -194,17 +200,18 @@ namespace tp {
|
|||
if (head->exactNode(key)) {
|
||||
if (head->mRight && head->mLeft) {
|
||||
Node* min = minNode(head->mRight);
|
||||
head->data = min->data;
|
||||
head->mRight = removeUtil(head->mRight, min->getFindKey(head->mRight));
|
||||
auto const& newKey = min->getFindKey(head->mRight);
|
||||
injectNodeInstead(head, min);
|
||||
head->mRight = removeUtil(head->mRight, newKey);
|
||||
}
|
||||
else if (head->mRight) {
|
||||
head->data = head->mRight->data;
|
||||
injectNodeInstead(head, head->mRight);
|
||||
deleteNode(head->mRight);
|
||||
head->mRight = nullptr;
|
||||
mSize--;
|
||||
}
|
||||
else if (head->mLeft) {
|
||||
head->data = head->mLeft->data;
|
||||
injectNodeInstead(head, head->mLeft);
|
||||
deleteNode(head->mLeft);
|
||||
head->mLeft = nullptr;
|
||||
mSize--;
|
||||
|
|
@ -337,13 +344,19 @@ namespace tp {
|
|||
// TODO: incomplete test
|
||||
if (!head->descentLeft(head->mLeft->getFindKey(head))) return head;
|
||||
if (head->mLeft->mParent != head) return head;
|
||||
if (!head->mRight && head->mLeft->mHeight != head->mHeight - 1) return head;
|
||||
}
|
||||
|
||||
if (head->mRight) {
|
||||
if (!head->descentRight(head->mRight->getFindKey(head))) return head;
|
||||
if (head->mRight->mParent != head) return head;
|
||||
if (!head->mLeft && head->mRight->mHeight != head->mHeight - 1) return head;
|
||||
}
|
||||
|
||||
if (head->mLeft && head->mRight) {
|
||||
if (max(head->mLeft->mHeight, head->mRight->mHeight) != head->mHeight - 1) return head;
|
||||
}
|
||||
|
||||
int balance = getNodeHeight(head->mRight) - getNodeHeight(head->mLeft);
|
||||
|
||||
if (balance > 1 || balance < -1) return head;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,106 @@ TEST_DEF_STATIC(Simple) {
|
|||
TEST(tree.head() == nullptr);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Persistance) {
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, TestAllocator> tree;
|
||||
|
||||
const auto size = 1000;
|
||||
|
||||
struct Item {
|
||||
Item() : data(0) {}
|
||||
bool presents = false;
|
||||
TestClass data;
|
||||
};
|
||||
|
||||
Item buff[size];
|
||||
|
||||
for (auto i : Range(size)) {
|
||||
buff[i].data.setVal(i);
|
||||
}
|
||||
|
||||
// random load
|
||||
ualni loadSize = 0;
|
||||
while (loadSize < size / 2) {
|
||||
ualni idx = rand() % (size - 1);
|
||||
DEBUG_ASSERT(idx < size)
|
||||
if (!buff[idx].presents) {
|
||||
tree.insert((alni) buff[idx].data.getVal(), buff[idx].data);
|
||||
loadSize++;
|
||||
buff[idx].presents = true;
|
||||
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == loadSize);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& item : buff) {
|
||||
if (item.presents) continue;
|
||||
tree.insert((alni) item.data.getVal(), item.data);
|
||||
loadSize++;
|
||||
item.presents = true;
|
||||
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == loadSize);
|
||||
}
|
||||
|
||||
TEST(tree.size() == size);
|
||||
TEST(tree.maxNode(tree.head())->data.getVal() == size - 1);
|
||||
TEST(tree.minNode(tree.head())->data.getVal() == 0);
|
||||
|
||||
// find
|
||||
for (auto item : buff) {
|
||||
auto node = tree.find((alni) item.data.getVal());
|
||||
TEST(node);
|
||||
if (!node) continue;
|
||||
TEST(node->data.getVal() == item.data.getVal());
|
||||
}
|
||||
|
||||
TEST(!tree.find(size + 1));
|
||||
TEST(!tree.find(-1));
|
||||
|
||||
// random unload
|
||||
ualni unloadSize = 0;
|
||||
while (unloadSize < size / 2) {
|
||||
ualni idx = rand() % (size - 1);
|
||||
if (buff[idx].presents) {
|
||||
|
||||
tree.remove((alni) buff[idx].data.getVal());
|
||||
|
||||
unloadSize++;
|
||||
buff[idx].presents = false;
|
||||
|
||||
// find
|
||||
for (auto item : buff) {
|
||||
if (!item.presents) continue;
|
||||
auto node = tree.find((alni) item.data.getVal());
|
||||
TEST(node);
|
||||
if (!node) continue;
|
||||
TEST(node->data.getVal() == item.data.getVal());
|
||||
}
|
||||
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == size - unloadSize);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& item : buff) {
|
||||
if (item.presents) {
|
||||
tree.remove((alni) item.data.getVal());
|
||||
unloadSize++;
|
||||
item.presents = false;
|
||||
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == size - unloadSize);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(tree.size() == 0);
|
||||
TEST(tree.head() == nullptr);
|
||||
TEST(tree.maxNode(tree.head()) == nullptr);
|
||||
TEST(tree.minNode(tree.head()) == nullptr);
|
||||
}
|
||||
|
||||
TEST_DEF(Avl) {
|
||||
testSimple();
|
||||
testPersistance();
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
#include "Module.hpp"
|
||||
|
||||
#include "Common.hpp"
|
||||
|
||||
int main() {
|
||||
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleBase, nullptr };
|
||||
tp::ModuleManifest TestModule("Test", nullptr, nullptr, ModuleDependencies);
|
||||
|
|
@ -11,5 +13,10 @@ int main() {
|
|||
|
||||
ASSERT(tp::gEnvironment.mWidth == tp::Environment::ArchWidth::X64);
|
||||
|
||||
ASSERT(tp::max(2, 1) == 2);
|
||||
ASSERT(tp::max(-1, 0) == 0);
|
||||
ASSERT(tp::max(0, -1) == 0);
|
||||
ASSERT(tp::min(0, -1) == -1);
|
||||
|
||||
TestModule.deinitialize();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue