// ::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::