Avl Test case passed

This commit is contained in:
IlushaShurupov 2023-06-30 09:08:50 +03:00
parent 2c94e02260
commit 88511539ac
3 changed files with 129 additions and 9 deletions

View file

@ -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;

View file

@ -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();
} }

View file

@ -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();
} }