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 descentLeft(AvlNumericKey in) const { return in.val < val; }
|
||||||
inline bool exactNode(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 getFindKey(/**/) const { return *this; }
|
||||||
inline AvlNumericKey keyInRightSubtree(AvlNumericKey in) const { return in.val; }
|
inline AvlNumericKey keyInRightSubtree(AvlNumericKey in) const { return in; }
|
||||||
inline AvlNumericKey keyInLeftSubtree(AvlNumericKey in) const { return in.val; }
|
inline AvlNumericKey keyInLeftSubtree(AvlNumericKey in) const { return in; }
|
||||||
|
|
||||||
inline void updateTreeCacheCallBack() {}
|
inline void updateTreeCacheCallBack() {}
|
||||||
};
|
};
|
||||||
|
|
@ -47,7 +47,7 @@ namespace tp {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline bool descentRight(KeyArg aKey) const { return key.descentRight(aKey); }
|
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 bool exactNode(KeyArg aKey) const { return key.exactNode(aKey); }
|
||||||
|
|
||||||
inline KeyArg getFindKey(const Node* node = nullptr) const { return key.getFindKey(/*node*/); }
|
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);
|
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;
|
return node ? node->mHeight : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,17 +200,18 @@ namespace tp {
|
||||||
if (head->exactNode(key)) {
|
if (head->exactNode(key)) {
|
||||||
if (head->mRight && head->mLeft) {
|
if (head->mRight && head->mLeft) {
|
||||||
Node* min = minNode(head->mRight);
|
Node* min = minNode(head->mRight);
|
||||||
head->data = min->data;
|
auto const& newKey = min->getFindKey(head->mRight);
|
||||||
head->mRight = removeUtil(head->mRight, min->getFindKey(head->mRight));
|
injectNodeInstead(head, min);
|
||||||
|
head->mRight = removeUtil(head->mRight, newKey);
|
||||||
}
|
}
|
||||||
else if (head->mRight) {
|
else if (head->mRight) {
|
||||||
head->data = head->mRight->data;
|
injectNodeInstead(head, head->mRight);
|
||||||
deleteNode(head->mRight);
|
deleteNode(head->mRight);
|
||||||
head->mRight = nullptr;
|
head->mRight = nullptr;
|
||||||
mSize--;
|
mSize--;
|
||||||
}
|
}
|
||||||
else if (head->mLeft) {
|
else if (head->mLeft) {
|
||||||
head->data = head->mLeft->data;
|
injectNodeInstead(head, head->mLeft);
|
||||||
deleteNode(head->mLeft);
|
deleteNode(head->mLeft);
|
||||||
head->mLeft = nullptr;
|
head->mLeft = nullptr;
|
||||||
mSize--;
|
mSize--;
|
||||||
|
|
@ -337,13 +344,19 @@ namespace tp {
|
||||||
// TODO: incomplete test
|
// TODO: incomplete test
|
||||||
if (!head->descentLeft(head->mLeft->getFindKey(head))) return head;
|
if (!head->descentLeft(head->mLeft->getFindKey(head))) return head;
|
||||||
if (head->mLeft->mParent != 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->mRight) {
|
||||||
if (!head->descentRight(head->mRight->getFindKey(head))) return head;
|
if (!head->descentRight(head->mRight->getFindKey(head))) return head;
|
||||||
if (head->mRight->mParent != 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);
|
int balance = getNodeHeight(head->mRight) - getNodeHeight(head->mLeft);
|
||||||
|
|
||||||
if (balance > 1 || balance < -1) return head;
|
if (balance > 1 || balance < -1) return head;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,106 @@ TEST_DEF_STATIC(Simple) {
|
||||||
TEST(tree.head() == nullptr);
|
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) {
|
TEST_DEF(Avl) {
|
||||||
testSimple();
|
testSimple();
|
||||||
|
testPersistance();
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
#include "Module.hpp"
|
#include "Module.hpp"
|
||||||
|
|
||||||
|
#include "Common.hpp"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleBase, nullptr };
|
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleBase, nullptr };
|
||||||
tp::ModuleManifest TestModule("Test", nullptr, nullptr, ModuleDependencies);
|
tp::ModuleManifest TestModule("Test", nullptr, nullptr, ModuleDependencies);
|
||||||
|
|
@ -11,5 +13,10 @@ int main() {
|
||||||
|
|
||||||
ASSERT(tp::gEnvironment.mWidth == tp::Environment::ArchWidth::X64);
|
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();
|
TestModule.deinitialize();
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue