feat: add isRed and setChild

This commit is contained in:
dualfroz committed 2026-09-06 19:35:17 +02:00
1 parent a4b9260215
commit cb70b0769a
1 file changed
+157
+157
View File
@@ -0,0 +1,157 @@
#include "rbt.h"
static bool isRed(const RbtNode* n)
{
return n != nullptr && n->red;
}
static void setChild(RbTree* t, RbtNode* parent, RbtNode* oldChild, RbtNode* newChild)
{
if (parent == nullptr)
t->root = newChild;
else if (parent->left == oldChild)
parent->left = newChild;
else
parent->right = newChild;
}
static void rotateLeft(RbTree* t, RbtNode* x)
{
RbtNode* y = x->right;
x->right = y->left;
if (y->left != nullptr)
y->left->parent = x;
y->parent = x->parent;
setChild(t, x->parent, x, y);
y->left = x;
x->parent = y;
}
static void rotateRight(RbTree* t, RbtNode* x)
{
RbtNode* y = x->left;
x->left = y->right;
if (y->right != nullptr)
y->right->parent = x;
y->parent = x->parent;
setChild(t, x->parent, x, y);
y->right = x;
x->parent = y;
}
static void insertFixup(RbTree* t, RbtNode* z)
{
while (isRed(z->parent)) {
RbtNode* parent = z->parent;
RbtNode* grandparent = parent->parent;
if (parent == grandparent->left) {
RbtNode* uncle = grandparent->right;
if (isRed(uncle)) {
parent->red = false;
uncle->red = false;
grandparent->red = true;
z = grandparent;
} else {
if (z == parent->right) {
z = parent;
rotateLeft(t, z);
parent = z->parent;
}
parent->red = false;
grandparent->red = true;
rotateRight(t, grandparent);
}
} else {
RbtNode* uncle = grandparent->left;
if (isRed(uncle)) {
parent->red = false;
uncle->red = false;
grandparent->red = true;
z = grandparent;
} else {
if (z == parent->left) {
z = parent;
rotateRight(t, z);
parent = z->parent;
}
parent->red = false;
grandparent->red = true;
rotateLeft(t, grandparent);
}
}
}
t->root->red = false;
}
static void removeFixup(RbTree* t, RbtNode* x, RbtNode* xParent)
{
while (x != t->root && !isRed(x)) {
if (x == xParent->left) {
RbtNode* w = xParent->right;
if (isRed(w)) {
w->red = false;
xParent->red = true;
rotateLeft(t, xParent);
w = xParent->right;
}
if (!isRed(w->left) && !isRed(w->right)) {
w->red = true;
x = xParent;
xParent = x->parent;
} else {
if (!isRed(w->right)) {
if (w->left != nullptr)
w->left->red = false;
w->red = true;
rotateRight(t, w);
w = xParent->right;
}
w->red = xParent->red;
xParent->red = false;
if (w->right != nullptr)
w->right->red = false;
rotateLeft(t, xParent);
x = t->root;
xParent = nullptr;
}
} else {
RbtNode* w = xParent->left;
if (isRed(w)) {
w->red = false;
xParent->red = true;
rotateRight(t, xParent);
w = xParent->left;
}
if (!isRed(w->left) && !isRed(w->right)) {
w->red = true;
x = xParent;
xParent = x->parent;
} else {
if (!isRed(w->left)) {
if (w->right != nullptr)
w->right->red = false;
w->red = true;
rotateLeft(t, w);
w = xParent->left;
}
w->red = xParent->red;
xParent->red = false;
if (w->left != nullptr)
w->left->red = false;
rotateRight(t, xParent);
x = t->root;
xParent = nullptr;
}
}
}
if (x != nullptr)
x->red = false;
}
void rbtInit(RbTree* t)
{
t->root = nullptr;
t->count = 0;
}