feat: add rbtInsert and rbtRemove to rbt
This commit is contained in:
1 parent
cb70b0769a
commit
8a61744dc0
1 file changed
+156
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user