From 8a61744dc0ce9a7e181124ebb31638bfd1edadf9 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Sun, 6 Sep 2026 19:53:02 +0200 Subject: [PATCH] feat: add rbtInsert and rbtRemove to rbt --- src/rbt.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/src/rbt.c b/src/rbt.c index 8afc949..81fb69d 100644 --- a/src/rbt.c +++ b/src/rbt.c @@ -155,3 +155,159 @@ void rbtInit(RbTree* t) t->count = 0; } +bool rbtInsert(RbTree* t, RbtNode* node, RbtCompareFn compare) +{ + RbtNode* parent = nullptr; + RbtNode* cur = t->root; + bool goLeft = false; + + while (cur != nullptr) { + int c = compare(node, cur); + if (c == 0) + return false; + parent = cur; + goLeft = c < 0; + cur = goLeft ? cur->left : cur->right; + } + + node->left = nullptr; + node->right = nullptr; + node->parent = parent; + node->red = true; + + if (parent == nullptr) + t->root = node; + else if (goLeft) + parent->left = node; + else + parent->right = node; + + t->count++; + insertFixup(t, node); + return true; +} + +void rbtRemove(RbTree* t, RbtNode* z) +{ + RbtNode* y = z; + bool yOriginalRed = y->red; + RbtNode* x; + RbtNode* xParent; + + if (z->left == nullptr) { + x = z->right; + xParent = z->parent; + setChild(t, z->parent, z, z->right); + if (z->right != nullptr) + z->right->parent = z->parent; + } else if (z->right == nullptr) { + x = z->left; + xParent = z->parent; + setChild(t, z->parent, z, z->left); + if (z->left != nullptr) + z->left->parent = z->parent; + } else { + y = z->right; + while (y->left != nullptr) + y = y->left; + yOriginalRed = y->red; + x = y->right; + + if (y->parent == z) { + xParent = y; + } else { + xParent = y->parent; + setChild(t, y->parent, y, y->right); + if (y->right != nullptr) + y->right->parent = y->parent; + y->right = z->right; + y->right->parent = y; + } + + setChild(t, z->parent, z, y); + y->parent = z->parent; + y->left = z->left; + y->left->parent = y; + y->red = z->red; + } + + t->count--; + if (!yOriginalRed) + removeFixup(t, x, xParent); +} + +RbtNode* rbtFind(const RbTree* t, const void* key, RbtLookupFn lookup) +{ + RbtNode* cur = t->root; + while (cur != nullptr) { + int c = lookup(key, cur); + if (c == 0) + return cur; + cur = c < 0 ? cur->left : cur->right; + } + return nullptr; +} + +RbtNode* rbtFirst(const RbTree* t) +{ + RbtNode* n = t->root; + if (n == nullptr) + return nullptr; + while (n->left != nullptr) + n = n->left; + return n; +} + +RbtNode* rbtLast(const RbTree* t) +{ + RbtNode* n = t->root; + if (n == nullptr) + return nullptr; + while (n->right != nullptr) + n = n->right; + return n; +} + +RbtNode* rbtNext(const RbtNode* node) +{ + if (node->right != nullptr) { + RbtNode* n = node->right; + while (n->left != nullptr) + n = n->left; + return n; + } + RbtNode* n = (RbtNode*)node; + RbtNode* parent = n->parent; + while (parent != nullptr && n == parent->right) { + n = parent; + parent = parent->parent; + } + return parent; +} + +RbtNode* rbtPrev(const RbtNode* node) +{ + if (node->left != nullptr) { + RbtNode* n = node->left; + while (n->right != nullptr) + n = n->right; + return n; + } + RbtNode* n = (RbtNode*)node; + RbtNode* parent = n->parent; + while (parent != nullptr && n == parent->left) { + n = parent; + parent = parent->parent; + } + return parent; +} + +usize rbtCount(const RbTree* t) +{ + return t->count; +} + +bool rbtIsEmpty(const RbTree* t) +{ + return t->root == nullptr; +}