/************************************************************************ Rebalance the right sub-tree after deletion. @return node to rebalance if more rebalancing required else NULL */ static ib_rbt_node_t* rbt_balance_right( /*==============*/ const ib_rbt_node_t* nil, /*!< in: rb tree nil node */ ib_rbt_node_t* parent, /*!< in: parent node */ ib_rbt_node_t* sibling) /*!< in: sibling node */ { ib_rbt_node_t* node = NULL; ut_a(sibling != nil); /* Case 3. */ if (sibling->color == IB_RBT_RED) { parent->color = IB_RBT_RED; sibling->color = IB_RBT_BLACK; rbt_rotate_left(nil, parent); sibling = parent->right; ut_a(sibling != nil); } /* Since this will violate case 3 because of the change above. */ if (sibling->left->color == IB_RBT_BLACK && sibling->right->color == IB_RBT_BLACK) { node = parent; /* Parent needs to be rebalanced too. */ sibling->color = IB_RBT_RED; } else { if (sibling->right->color == IB_RBT_BLACK) { ut_a(sibling->left->color == IB_RBT_RED); sibling->color = IB_RBT_RED; sibling->left->color = IB_RBT_BLACK; rbt_rotate_right(nil, sibling); sibling = parent->right; ut_a(sibling != nil); } sibling->color = parent->color; sibling->right->color = IB_RBT_BLACK; parent->color = IB_RBT_BLACK; rbt_rotate_left(nil, parent); } return(node); }
struct rbnode * rbt_insert_node(struct rbnode *r,int key,void *val,int szval) { if(r==NULL) { struct rbnode *item; item=malloc(sizeof(struct rbnode)); if(!item) return NULL; rbt_node_init(item); rbt_node_fill(item,key,val,szval); return item; } if(key < r->key) { r->lchild=rbt_insert_node(r->lchild,key,val,szval); } else if (key > r->key) { r->rchild=rbt_insert_node(r->rchild,key,val,szval); } else { r->dsz=szval; } if(rbt_isred(r->rchild) && !rbt_isred(r->lchild)) { r=rbt_rotate_left(r); } if(rbt_isred(r->lchild) && rbt_isred(r->lchild->lchild)) { r=rbt_rotate_right(r); } if(rbt_isred(r->lchild) && rbt_isred(r->rchild)) { rbt_flipcolor(r); } return r; }
/************************************************************************ Balance a tree after inserting a node. */ static void rbt_balance_tree( /*=============*/ const ib_rbt_t* tree, /*!< in: tree to balance */ ib_rbt_node_t* node) /*!< in: node that was inserted */ { const ib_rbt_node_t* nil = tree->nil; ib_rbt_node_t* parent = node->parent; /* Restore the red-black property. */ node->color = IB_RBT_RED; while (node != ROOT(tree) && parent->color == IB_RBT_RED) { ib_rbt_node_t* grand_parent = parent->parent; if (parent == grand_parent->left) { ib_rbt_node_t* uncle = grand_parent->right; if (uncle->color == IB_RBT_RED) { /* Case 1 - change the colors. */ uncle->color = IB_RBT_BLACK; parent->color = IB_RBT_BLACK; grand_parent->color = IB_RBT_RED; /* Move node up the tree. */ node = grand_parent; } else { if (node == parent->right) { /* Right is a black node and node is to the right, case 2 - move node up and rotate. */ node = parent; rbt_rotate_left(nil, node); } grand_parent = node->parent->parent; /* Case 3. */ node->parent->color = IB_RBT_BLACK; grand_parent->color = IB_RBT_RED; rbt_rotate_right(nil, grand_parent); } } else { ib_rbt_node_t* uncle = grand_parent->left; if (uncle->color == IB_RBT_RED) { /* Case 1 - change the colors. */ uncle->color = IB_RBT_BLACK; parent->color = IB_RBT_BLACK; grand_parent->color = IB_RBT_RED; /* Move node up the tree. */ node = grand_parent; } else { if (node == parent->left) { /* Left is a black node and node is to the right, case 2 - move node up and rotate. */ node = parent; rbt_rotate_right(nil, node); } grand_parent = node->parent->parent; /* Case 3. */ node->parent->color = IB_RBT_BLACK; grand_parent->color = IB_RBT_RED; rbt_rotate_left(nil, grand_parent); } } parent = node->parent; } /* Color the root black. */ ROOT(tree)->color = IB_RBT_BLACK; }
void rbt_paint_onremove(rbt_t *rbt, rbt_node_t *node) { if (!node) return; // delete case 1 if (node->parent != NULL) { // delete case 2 rbt_node_t *sibling = rbt_sibling(node); if (IS_RED(sibling)) { PAINT_RED(node->parent); PAINT_BLACK(sibling); if (node == node->parent->left) { rbt_rotate_left(rbt, node->parent); } else { rbt_rotate_right(rbt, node->parent); } } // delete case 3 if (IS_BLACK(node->parent) && sibling && IS_BLACK(sibling) && IS_BLACK(sibling->left) && IS_BLACK(sibling->right)) { PAINT_RED(sibling); rbt_paint_onremove(rbt, node->parent); } else { // delete case 4 if (IS_RED(node->parent) && sibling && IS_BLACK(sibling) && IS_BLACK(sibling->left) && IS_BLACK(sibling->right)) { PAINT_RED(sibling); PAINT_BLACK(node->parent); } else { // delete case 5 if (IS_BLACK(sibling)) { if (node == node->parent->left && sibling && IS_BLACK(sibling->right) && IS_RED(sibling->left)) { PAINT_RED(sibling); PAINT_BLACK(sibling->left); rbt_rotate_right(rbt, sibling); } else if (node == node->parent->right && sibling && IS_BLACK(sibling->left) && IS_RED(sibling->right)) { PAINT_RED(sibling); PAINT_BLACK(sibling->right); rbt_rotate_left(rbt, sibling); } } // delete case 6 if (sibling) sibling->color = node->parent->color; PAINT_BLACK(node->parent); if (node == node->parent->left) { if (sibling) PAINT_BLACK(sibling->right); rbt_rotate_left(rbt, node->parent); } else { if (sibling) PAINT_BLACK(sibling->left); rbt_rotate_right(rbt, node->parent); } } } } }
int rbt_add(rbt_t *rbt, void *k, size_t klen, void *v) { int rc = 0; rbt_node_t *node = calloc(1, sizeof(rbt_node_t)); node->key = malloc(klen); memcpy(node->key, k, klen); node->klen = klen; node->value = v; if (!rbt->root) { PAINT_BLACK(node); rbt->root = node; } else { rc = _rbt_add_internal(rbt, rbt->root, node); if (IS_BLACK(node)) { // if the node just added is now black it means // it was already existing and this was only a value update if (!node->parent) { // we need to check also if the root pointer // should be updated as well rbt->root = node; } return 1; } if (!node->parent) { // case 1 PAINT_BLACK(node); rbt->root = node; } else if (IS_BLACK(node->parent)) { // case 2 return rc; } else { // case 3 rbt_node_t *uncle = rbt_uncle(node); rbt_node_t *grandparent = rbt_grandparent(node); if (IS_RED(uncle)) { PAINT_BLACK(node->parent); PAINT_BLACK(uncle); if (grandparent) { PAINT_RED(grandparent); rbt_add(rbt, grandparent->key, grandparent->klen, grandparent->value); } } else if (grandparent) { // case 4 if (node == node->parent->right && node->parent == grandparent->left) { rbt_rotate_left(rbt, node->parent); node = node->left; } else if (node == node->parent->left && node->parent == grandparent->right) { rbt_rotate_right(rbt, node->parent); node = node->right; } // case 5 grandparent = rbt_grandparent(node); if (node->parent) { PAINT_BLACK(node->parent); PAINT_RED(grandparent); if (node == node->parent->left) rbt_rotate_right(rbt, grandparent); else rbt_rotate_left(rbt, grandparent); } else { fprintf(stderr, "Corrupted tree\n"); return -1; } } } } return rc; }