/* * Fixup required to delete an internal node, rotating left-leaning red links to the right. * * Parameters: * - ptn = Pointer to root of subtree to be fixed up. * * Returns: * Pointer to root of subtree after fixup. */ static PRBTREENODE move_red_right(PRBTREENODE ptn) { color_flip(ptn); if (ptn->ptnLeft && rbtIsRed(ptn->ptnLeft->ptnLeft)) { ptn = rotate_right(ptn); color_flip(ptn); } return ptn; }
/* * Fixup required to delete the leftmost node; we maintain the invariant that either the current node * or its left child is red. After a color flip, we resolve any successive reds on the right with rotations * and another color flip. * * Parameters: * - ptn = Pointer to root of subtree to be fixed up. * * Returns: * Pointer to root of subtree after fixup. */ static PRBTREENODE move_red_left(PRBTREENODE ptn) { color_flip(ptn); if (rbtNodeRight(ptn) && rbtIsRed(rbtNodeRight(ptn)->ptnLeft)) { rbtSetNodeRight(ptn, rotate_right(rbtNodeRight(ptn))); ptn = rotate_left(ptn); color_flip(ptn); } return ptn; }
static void insert_fix_up(rbtree_t rb,struct rbnode *n) { while(n->parent->color == RED) { struct rbnode *parent = n->parent; struct rbnode *grand_parent = parent->parent; if(parent == grand_parent->left) { struct rbnode *ancle = grand_parent->right; if(ancle->color == RED) { color_flip(grand_parent); n = grand_parent; } else { if(n == parent->right) { n = parent; rotate_left(rb,n); } n->parent->color = BLACK; n->parent->parent->color = RED; rotate_right(rb,n->parent->parent); } } else { struct rbnode *ancle = grand_parent->left; if(ancle->color == RED) { color_flip(grand_parent); n = grand_parent; } else { if(n == parent->left) { n = parent; rotate_right(rb,n); } n->parent->color = BLACK; n->parent->parent->color = RED; rotate_left(rb,n->parent->parent); } } } rb->root->color = BLACK; }
struct rbtree *rb_insert(struct rbtree *tree, struct rbtree *node) { node->left = node->right = NULL; node->red = false; if (!tree) { node->red = true; return node; } if (is_red(tree->left) && is_red(tree->right)) color_flip(tree); if (node->key < tree->key) tree->left = rb_insert(tree->left, node); else tree->right = rb_insert(tree->right, node); if (is_red(tree->right)) tree = rotate_left(tree); if (is_red(tree->left) && is_red(tree->left->left)) tree = rotate_right(tree); return tree; }
/* * Fixes up the given subtree after an insertion or deletion, to ensure that it maintains the invariants * that no two consecutive links in the tree may be red, and that all red links must lean left. * * Parameters: * - ptn = Pointer to the root node of the subtree to be fixed up. * * Returns: * Pointer to the new root node of the subtree after fixup is performed. */ static PRBTREENODE fix_up(PRBTREENODE ptn) { if (rbtIsRed(rbtNodeRight(ptn)) && !rbtIsRed(ptn->ptnLeft)) ptn = rotate_left(ptn); if (rbtIsRed(ptn->ptnLeft) && rbtIsRed(ptn->ptnLeft->ptnLeft)) ptn = rotate_right(ptn); if (rbtIsRed(ptn->ptnLeft) && rbtIsRed(rbtNodeRight(ptn))) color_flip(ptn); return ptn; }