static void bst_insert_repair(bst *t, bstnode *n) { bstnode *u; /* case 1: n is the root */ if (!n->parent) { n->color = BLACK; return; } /* case 2: n's parent is black */ if (n->parent->color == BLACK) return; /* case 3: n's uncle and father are both red */ if ((u = UNCLE(n)) && u->color == RED) { n->parent->color = BLACK; u->color = BLACK; GRANDPARENT(n)->color = RED; bst_insert_repair(t, GRANDPARENT(n)); return; } /* case 4: n has no or black uncle, red father and either n = n->parent->right && n->parent = n->parent->parent->left or n = n->parent->left && n->parent = n->parent->parent->right */ if (IS_RIGHT_CHILD(n) && IS_LEFT_CHILD(n->parent)) { bst_rotate_left(t, n->parent); n = n->left; } else if (IS_LEFT_CHILD(n) && IS_RIGHT_CHILD(n->parent)) { bst_rotate_right(t, n->parent); n = n->right; } /* case 5: n has no or black uncle, red father and either n = n->parent->left && n->parent = n->parent->parent->left or n = n->parent->right && n->parent = n->parent->parent->right */ n->parent->color = BLACK; GRANDPARENT(n)->color = RED; if (IS_LEFT_CHILD(n)) bst_rotate_right(t, GRANDPARENT(n)); else { bst_rotate_left(t, GRANDPARENT(n)); } }
static void bst_remove_at(bst *t, bstnode *n) { bstnode *p; /* n has two children */ if (!IS_LEAF(n->left) && !IS_LEAF(n->right)) { static int del_from_left = 1; long tmpkey; void *tmpdata; if (del_from_left) { p = n->left; while (!IS_LEAF(p->right)) p = p->right; } else { p = n->right; while (!IS_LEAF(p->left)) p = p->left; } /* swap key and data and remove swapped node (which has 0 or 1 child) */ tmpkey = p->key, p->key = n->key, n->key = tmpkey; tmpdata = p->data, p->data = n->data, n->data = tmpdata; bst_remove_at(t, p); return; } /* n has no/one child */ p = IS_LEAF(n->left) ? n->right : n->left; /* replace n with p */ p->parent = n->parent; if (n->parent) { if (IS_LEFT_CHILD(n)) n->parent->left = p; else n->parent->right = p; } else t->root = p; if (IS_BLACK(n)) { if (p->color == RED) p->color = BLACK; else bst_remove_repair(t, p); } free(n); return; }
/* Rotate right helper function: * * A * / \ * B a * / \ * b c * * Becomes : * B * / \ * A a * / \ * b c * */ void rotate_right(struct node *x, struct node **root) { struct node *y = x->p; if(IS_LEFT_CHILD(y)) y->p->l = x; else y->p->r = x; x->p = y->p; y->l = x->r; y->l->p = y; x->r = y; y->p = x; /* Edge case, new x is the root?? */ if (IS_NIL(x->p)) *root = x; }
static void bst_remove_repair(bst *t, bstnode *n) { bstnode *sib; /* case 1: n is root */ if (!n->parent) return; sib = SIBLING(n); /* case 2: n's sibling is red */ if (IS_RED(sib)) { n->parent->color = RED; sib->color = BLACK; if (IS_LEFT_CHILD(n)) bst_rotate_left(t, n->parent); else bst_rotate_right(t, n->parent); sib = SIBLING(n); } /* case 3: parent sib and sib's children are black */ if (n->parent->color == BLACK && sib->color == BLACK && IS_BLACK(sib->left) && IS_BLACK(sib->right)) { sib->color = RED; bst_remove_repair(t, n->parent); return; } /* case 4: parent is red, sib and sib's children are black */ if (n->parent->color == RED && sib->color == BLACK && IS_BLACK(sib->left) && IS_BLACK(sib->right)) { sib->color = RED; n->parent->color = BLACK; return; } /* case 5: a) n is left child, sib and sib->right child are black, sib->left is red b) n is right child, sib and sib->left child are black, sib->right is red */ if (IS_LEFT_CHILD(n) && sib->color == BLACK && IS_RED(sib->left) && IS_BLACK(sib->right)) { sib->color = RED; sib->left->color = BLACK; bst_rotate_right(t, sib); sib = SIBLING(n); } else if (IS_RIGHT_CHILD(n) && sib->color == BLACK && IS_RED(sib->right) && IS_BLACK(sib->left)) { sib->color = RED; sib->right->color = BLACK; bst_rotate_left(t, sib); sib = SIBLING(n); } /* case 6: */ sib->color = n->parent->color; n->parent->color = BLACK; if (IS_LEFT_CHILD(n)) { sib->right->color = BLACK; bst_rotate_left(t, n->parent); } else { sib->left->color = BLACK; bst_rotate_right(t, n->parent); } }