Gears-C/src/ds.c
2025-04-14 16:37:47 +10:00

330 lines
6.1 KiB
C

// ::DataStructures::Globals::Start::
RBNode RB_NIL = { .color = RB_BLACK };
// ::DataStructures::Globals::End::
// ::DataStructures::RedBlackTree::Functions::Start::
static void CreateRBTree(RBTree *tree)
{
Assert(tree != NULL, "RBTree is null");
RB_NIL.right = RB_NIL.left = RB_NIL.parent = &RB_NIL;
tree->root = &RB_NIL;
tree->nil = &RB_NIL;
}
static void RBTreeInsert(RBTree *tree, RBNode *node)
{
node->left = node->right = tree->nil;
node->color = RB_RED;
if (tree->root == tree->nil)
{
node->color = RB_BLACK;
node->parent = tree->nil;
tree->root = node;
}
else
{
RBNode *curr_node = tree->root;
while (true)
{
Assert(curr_node != tree->nil, "Current Node is NIL");
if (curr_node->value < node->value)
{
if (curr_node->right == tree->nil)
{
node->parent = curr_node;
curr_node->right = node;
break;
}
else
{
curr_node = curr_node->right;
}
}
else
{
if (curr_node->left == tree->nil)
{
node->parent = curr_node;
curr_node->left = node;
break;
}
else
{
curr_node = curr_node->left;
}
}
}
}
if (node->parent->color != RB_BLACK)
RBTreeCorrect(tree, node);
}
static void RBTreeCorrect(RBTree *tree, RBNode *node)
{
RBNode *gp = node->parent->parent;
RBNode *p = node->parent;
do
{
if (node == tree->root)
{
node->color = RB_BLACK;
break;
}
if (gp == tree->nil)
{
p->color = RB_BLACK;
break;
}
RBNodeDir dir = NodeDir(p);
RBNode *unc = gp->child[1 - dir];
if (unc == tree->nil || unc->color == RB_BLACK)
{
if (node == p->child[1 - dir])
{
RBTreeRotate(tree, p, dir);
node = p;
p = gp->child[dir];
}
RBTreeRotate(tree, gp, 1 - dir);
p->color = RB_BLACK;
gp->color = RB_RED;
break;
}
p->color = RB_BLACK;
unc->color = RB_BLACK;
gp->color = RB_RED;
node = gp;
gp = node->parent->parent;
} while ((p = node->parent));
}
static void RBTreeDelete(RBTree *tree, i32 value)
{
RBNode *node = NULL;
Assert(RBTreeSearch(tree, value, &node), "Unable to find node in RBTreeDelete");
if (node == tree->root && node->left == tree->nil && node->right == tree->nil)
{
tree->root = tree->nil;
}
else if (node->left != tree->nil && node->right != tree->nil)
{
RBNode *ln = node->right;
while (ln->left != tree->nil)
ln = ln->left;
node->value = ln->value;
node->data = ln->data;
if (node->right == ln)
node->right = tree->nil;
else
ln->parent->left = tree->nil;
ln->parent = tree->nil;
}
else if (node->color == RB_BLACK && node->left != tree->nil)
{
node->value = node->left->value;
node->data = node->left->data;
node->left = tree->nil;
}
else if (node->color == RB_BLACK && node->right != tree->nil)
{
node->value = node->right->value;
node->data = node->right->data;
node->right = tree->nil;
}
else if (node->color == RB_RED && node->right == tree->nil && node->left == tree->nil)
{
RBNodeDir dir = NodeDir(node);
node->parent->child[dir] = tree->nil;
}
else
{
RBNode *p = node->parent;
RBNodeColor col = node->color;
RBNode *s, *cn, *dn;
RBNodeDir dir = NodeDir(node);
p->child[dir] = tree->nil;
goto start_deletion;
do
{
dir = NodeDir(node);
start_deletion:
s = p->child[1 - dir];
dn = s->child[1 - dir];
cn = s->child[dir];
if (s->color == RB_RED)
{
RBTreeRotate(tree, p, dir);
p->color = RB_RED;
s->color = RB_BLACK;
s = cn;
dn = s->child[1 - dir];
if (dn->color == RB_RED)
goto rotate_sibling;
cn = s->child[dir];
if (cn->color == RB_RED)
goto rotate_parent;
s->color = RB_RED;
p->color = RB_BLACK;
return;
}
if (dn->color == RB_RED)
goto rotate_parent;
if (cn->color == RB_RED)
goto rotate_sibling;
if (p->color == RB_RED)
{
s->color = RB_RED;
p->color = RB_BLACK;
return;
}
if (p == tree->nil)
return;
s->color = RB_RED;
node = p;
} while ((p = node->parent));
rotate_sibling:
RBTreeRotate(tree, s, 1 - dir);
s->color = RB_RED;
cn->color = RB_BLACK;
dn = s;
s = cn;
rotate_parent:
RBTreeRotate(tree, p, dir);
s->color = p->color;
p->color = RB_BLACK;
dn->color = RB_BLACK;
}
}
static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node)
{
if (tree->root == tree->nil) return false;
b32 found = false;
RBNode *node = tree->root;
while (true)
{
if (node->value == value)
{
found = true;
break;
}
if (node == tree->nil)
break;
if (node->value < value)
node = node->right;
else
node = node->left;
}
if (found)
*out_node = node;
return found;
}
static inline void RBTreeTransplant(RBTree *tree, RBNode *node, RBNode *placed_node)
{
if (node->parent == tree->nil)
tree->root = placed_node;
else if (node == node->parent->left)
node->parent->left = placed_node;
else
node->parent->right = placed_node;
placed_node->parent = node->parent;
}
static void RBTreeRotate(RBTree *tree, RBNode *node, RBNodeDir dir)
{
RBNode *p = node->parent;
RBNode *root = node->child[1 - dir];
RBNode *child = root->child[dir];
node->child[1 - dir] = child;
if (child != tree->nil)
child->parent = node;
root->child[dir] = node;
root->parent = p;
node->parent = root;
if (p != tree->nil)
p->child[node == p->right] = root;
else
tree->root = root;
}
static void RBTreeLeftRotate(RBTree *tree, RBNode *node)
{
RBNode *right = node->right;
if (right->left != tree->nil)
node->right = right->left;
if (node->parent == tree->nil)
tree->root = right;
else if (node->parent->left == node)
node->parent->left = right;
else
node->parent->right = right;
right->parent = node->parent;
right->left = node;
node->parent = right;
}
static void RBTreeRightRotate(RBTree *tree, RBNode *node)
{
RBNode *left = node->left;
if (left->right != tree->nil)
node->left = left->right;
if (node->parent == tree->nil)
tree->root = left;
else if (node->parent->left == node)
node->parent->left = left;
else
node->parent->right = left;
left->parent = node->parent;
left->right = node;
node->parent = left;
}
// ::DataStructures::RedBlackTree::Functions::Start::