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

View file

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