/* * Maintain Red-Black tree balance after inserting node x. * * The newly inserted node is always initially marked red. That may lead to * a situation where a red node has a red child, which is prohibited. We can * always fix the problem by a series of color changes and/or "rotations", * which move the problem progressively higher up in the tree. If one of the * two red nodes is the root, we can always fix the problem by changing the * root from red to black. * * (This does not work lower down in the tree because we must also maintain * the invariant that every leaf has equal black-height.) */ static void rb_insert_fixup(RBTree *rb, RBNode *x) { /* * x is always a red node. Initially, it is the newly inserted node. Each * iteration of this loop moves it higher up in the tree. */ while (x != rb->root && x->parent->color == RBRED) { /* * x and x->parent are both red. Fix depends on whether x->parent is * a left or right child. In either case, we define y to be the * "uncle" of x, that is, the other child of x's grandparent. * * If the uncle is red, we flip the grandparent to red and its two * children to black. Then we loop around again to check whether the * grandparent still has a problem. * * If the uncle is black, we will perform one or two "rotations" to * balance the tree. Either x or x->parent will take the * grandparent's position in the tree and recolored black, and the * original grandparent will be recolored red and become a child of * that node. This always leaves us with a valid red-black tree, so * the loop will terminate. */ if (x->parent == x->parent->parent->left) { RBNode *y = x->parent->parent->right; if (y->color == RBRED) { /* uncle is RBRED */ x->parent->color = RBBLACK; y->color = RBBLACK; x->parent->parent->color = RBRED; x = x->parent->parent; } else { /* uncle is RBBLACK */ if (x == x->parent->right) { /* make x a left child */ x = x->parent; rb_rotate_left(rb, x); } /* recolor and rotate */ x->parent->color = RBBLACK; x->parent->parent->color = RBRED; rb_rotate_right(rb, x->parent->parent); } } else { /* mirror image of above code */ RBNode *y = x->parent->parent->left; if (y->color == RBRED) { /* uncle is RBRED */ x->parent->color = RBBLACK; y->color = RBBLACK; x->parent->parent->color = RBRED; x = x->parent->parent; } else { /* uncle is RBBLACK */ if (x == x->parent->left) { x = x->parent; rb_rotate_right(rb, x); } x->parent->color = RBBLACK; x->parent->parent->color = RBRED; rb_rotate_left(rb, x->parent->parent); } } } /* * The root may already have been black; if not, the black-height of every * node in the tree increases by one. */ rb->root->color = RBBLACK; }
/* * Maintain Red-Black tree balance after deleting a black node. */ static void rb_delete_fixup(RBTree *rb, RBNode *x) { /* * x is always a black node. Initially, it is the former child of the * deleted node. Each iteration of this loop moves it higher up in the * tree. */ while (x != rb->root && x->color == RBBLACK) { /* * Left and right cases are symmetric. Any nodes that are children of * x have a black-height one less than the remainder of the nodes in * the tree. We rotate and recolor nodes to move the problem up the * tree: at some stage we'll either fix the problem, or reach the root * (where the black-height is allowed to decrease). */ if (x == x->parent->left) { RBNode *w = x->parent->right; if (w->color == RBRED) { w->color = RBBLACK; x->parent->color = RBRED; rb_rotate_left(rb, x->parent); w = x->parent->right; } if (w->left->color == RBBLACK && w->right->color == RBBLACK) { w->color = RBRED; x = x->parent; } else { if (w->right->color == RBBLACK) { w->left->color = RBBLACK; w->color = RBRED; rb_rotate_right(rb, w); w = x->parent->right; } w->color = x->parent->color; x->parent->color = RBBLACK; w->right->color = RBBLACK; rb_rotate_left(rb, x->parent); x = rb->root; /* Arrange for loop to terminate. */ } } else { RBNode *w = x->parent->left; if (w->color == RBRED) { w->color = RBBLACK; x->parent->color = RBRED; rb_rotate_right(rb, x->parent); w = x->parent->left; } if (w->right->color == RBBLACK && w->left->color == RBBLACK) { w->color = RBRED; x = x->parent; } else { if (w->left->color == RBBLACK) { w->right->color = RBBLACK; w->color = RBRED; rb_rotate_left(rb, w); w = x->parent->left; } w->color = x->parent->color; x->parent->color = RBBLACK; w->left->color = RBBLACK; rb_rotate_right(rb, x->parent); x = rb->root; /* Arrange for loop to terminate. */ } } } x->color = RBBLACK; }
void rb_rebalance (rb_node_t * node, rb_node_t ** root) { rb_node_t *parent, *gparent; node->rb_color = RB_RED; while ((parent = node->rb_parent) && parent->rb_color == RB_RED) { gparent = parent->rb_parent; if (parent == gparent->rb_left) { { register rb_node_t *uncle = gparent->rb_right; if (uncle && uncle->rb_color == RB_RED) { uncle->rb_color = RB_BLACK; parent->rb_color = RB_BLACK; gparent->rb_color = RB_RED; node = gparent; continue; } } if (parent->rb_right == node) { register rb_node_t *tmp; rb_rotate_left (parent, root); tmp = parent; parent = node; node = tmp; } parent->rb_color = RB_BLACK; gparent->rb_color = RB_RED; rb_rotate_right (gparent, root); } else { { register rb_node_t *uncle = gparent->rb_left; if (uncle && uncle->rb_color == RB_RED) { uncle->rb_color = RB_BLACK; parent->rb_color = RB_BLACK; gparent->rb_color = RB_RED; node = gparent; continue; } } if (parent->rb_left == node) { register rb_node_t *tmp; rb_rotate_right (parent, root); tmp = parent; parent = node; node = tmp; } parent->rb_color = RB_BLACK; gparent->rb_color = RB_RED; rb_rotate_left (gparent, root); } } (*root)->rb_color = RB_BLACK; }
/** 在树中的结点被删除后调整平衡 */ static rb_node_t* rb_erase_rebalance( rb_node_t *node, rb_node_t *parent, rb_node_t *root ) { rb_node_t *other, *o_left, *o_right; while ((!node || node->color == BLACK) && node != root) { if (parent->left == node) { other = parent->right; if (other->color == RED) { other->color = BLACK; parent->color = RED; root = rb_rotate_left(parent, root); other = parent->right; } if ((!other->left || other->left->color == BLACK) && (!other->right || other->right->color == BLACK)) { other->color = RED; node = parent; parent = node->parent; } else { if (!other->right || other->right->color == BLACK) { if ((o_left = other->left)) { o_left->color = BLACK; } other->color = RED; root = rb_rotate_right(other, root); other = parent->right; } other->color = parent->color; parent->color = BLACK; if (other->right) { other->right->color = BLACK; } root = rb_rotate_left(parent, root); node = root; break; } } else { other = parent->left; if (other->color == RED) { other->color = BLACK; parent->color = RED; root = rb_rotate_right(parent, root); other = parent->left; } if ((!other->left || other->left->color == BLACK) && (!other->right || other->right->color == BLACK)) { other->color = RED; node = parent; parent = node->parent; } else { if (!other->left || other->left->color == BLACK) { if ((o_right = other->right)) { o_right->color = BLACK; } other->color = RED; root = rb_rotate_left(other, root); other = parent->left; } other->color = parent->color; parent->color = BLACK; if (other->left) { other->left->color = BLACK; } root = rb_rotate_right(parent, root); node = root; break; } } } if( node ) { node->color = BLACK; } return root; }
rb_node_t* rb_delete_fixup(rb_node_t* root,rb_node_t* nodex) { rb_node_t* nodew; while(nodex == root && nodex->color == BLACK) { if(nodex == nodex->parent->lchild) { nodew = nodex->parent->rchild; if(nodew->color == RED) { nodew->color = BLACK; nodex->parent->color = RED; root = rb_rotate_left(root,nodex->parent); nodew = nodex->parent.rchild; } if(nodew->lchild->color == BLACK && nodew->rchild->color == BLACK) { nodew->color = RED; nodex = nodex->parent; } else { if(nodew->rchild->color == BLACK) { nodew->lchild->color = BLACK; nodew->color = RED; root = rb_rotate_right(root,nodew); nodew = nodex->parent->rchild; } nodew->color = nodex->parent->color; nodex->parent->color = BLACK; nodew->rchild->color = BLACK; root = rb_rotate_left(root,nodex->parent); nodex = root; } } else { nodew = nodex->parent->lchild; if(nodew->color == RED) { nodew->color = BLACK; nodex->parent->color = RED; root = rb_rotate_right(root,nodex->parent); nodew = nodex->parent.lchild; } if(nodew->lchild->color == BLACK && nodew->rchild->color == BLACK) { nodew->color = RED; nodex = nodex->parent; } else { if(nodew->lchild->color == BLACK) { nodew->rchild->color = BLACK; nodew->color = RED; root = rb_rotate_left(root,nodew); nodew = nodex->parent->lchild; } nodew->color = nodex->parent->color; nodex->parent->color = BLACK; nodew->lchild->color = BLACK; root = rb_rotate_right(root,nodex->parent); nodex = root; } } } nodex->color = BLACK; return root; }
static void rb_erase_rebalance (rb_node_t * child, rb_node_t * parent, rb_node_t ** root) { rb_node_t *other; while ((!child || child->rb_color == RB_BLACK) && child != *root) { if (parent->rb_left == child) { other = parent->rb_right; if (other->rb_color == RB_RED) { other->rb_color = RB_BLACK; parent->rb_color = RB_RED; rb_rotate_left (parent, root); other = parent->rb_right; } if ((!other->rb_left || other->rb_left->rb_color == RB_BLACK) && (!other->rb_right || other->rb_right->rb_color == RB_BLACK)) { other->rb_color = RB_RED; child = parent; parent = child->rb_parent; } else { if (!other->rb_right || other->rb_right->rb_color == RB_BLACK) { register rb_node_t *o_left; if ((o_left = other->rb_left)) o_left->rb_color = RB_BLACK; other->rb_color = RB_RED; rb_rotate_right (other, root); other = parent->rb_right; } other->rb_color = parent->rb_color; parent->rb_color = RB_BLACK; if (other->rb_right) other->rb_right->rb_color = RB_BLACK; rb_rotate_left (parent, root); child = *root; break; } } else { other = parent->rb_left; if (other->rb_color == RB_RED) { other->rb_color = RB_BLACK; parent->rb_color = RB_RED; rb_rotate_right (parent, root); other = parent->rb_left; } if ((!other->rb_left || other->rb_left->rb_color == RB_BLACK) && (!other->rb_right || other->rb_right->rb_color == RB_BLACK)) { other->rb_color = RB_RED; child = parent; parent = child->rb_parent; } else { if (!other->rb_left || other->rb_left->rb_color == RB_BLACK) { register rb_node_t *o_right; if ((o_right = other->rb_right)) o_right->rb_color = RB_BLACK; other->rb_color = RB_RED; rb_rotate_left (other, root); other = parent->rb_left; } other->rb_color = parent->rb_color; parent->rb_color = RB_BLACK; if (other->rb_left) other->rb_left->rb_color = RB_BLACK; rb_rotate_right (parent, root); child = *root; break; } } } if (child) child->rb_color = RB_BLACK; }
/** 在树中的结点被删除后调整平衡 */ static RBTreeNode* rb_erase_rebalance( RBTreeNode *node, RBTreeNode *parent, RBTreeNode *root ) { RBTreeNode *other, *o_left, *o_right; while( (!node || node->color == BLACK) && node != root ) { if( parent->left == node ) { other = parent->right; if( other->color == RED ) { other->color = BLACK; parent->color = RED; root = rb_rotate_left( parent, root ); other = parent->right; } if( (!other->left || other->left->color == BLACK) && (!other->right || other->right->color == BLACK) ) { other->color = RED; node = parent; parent = node->parent; continue; } if( !other->right || other->right->color == BLACK ) { if( (o_left = other->left) ) { o_left->color = BLACK; } other->color = RED; root = rb_rotate_right( other, root ); other = parent->right; } other->color = parent->color; parent->color = BLACK; if( other->right ) { other->right->color = BLACK; } root = rb_rotate_left( parent, root ); node = root; break; } other = parent->left; if( other->color == RED ) { other->color = BLACK; parent->color = RED; root = rb_rotate_right( parent, root ); other = parent->left; } if( (!other->left || other->left->color == BLACK) && (!other->right || other->right->color == BLACK) ) { other->color = RED; node = parent; parent = node->parent; continue; } if( !other->left || other->left->color == BLACK ) { if( (o_right = other->right) ) { o_right->color = BLACK; } other->color = RED; root = rb_rotate_left( other, root ); other = parent->left; } other->color = parent->color; parent->color = BLACK; if( other->left ) { other->left->color = BLACK; } root = rb_rotate_right( parent, root ); node = root; break; } if( node ) { node->color = BLACK; } return root; }
//七、红黑树的4种删除情况 //---------------------------------------------------------------- //红黑树修复删除的4种情况 //为了表示下述注释的方便,也为了让下述代码与我的倆篇文章相对应, //x表示要删除的结点,*other、w表示兄弟结点, //---------------------------------------------------------------- rb_node_t* rb_erase_fixup(rb_node_t *node, rb_node_t *parent, rb_node_t *root) { rb_node_t *other, *o_left, *o_right; //x的兄弟*other,兄弟左孩子*o_left,*o_right while ((!node || node->color == BLACK) && node != root) { if (parent->left == node) { other = parent->right; if (other->color == RED) //情况1:x的兄弟w是红色的 { other->color = BLACK; parent->color = RED; //上俩行,改变颜色,w->黑、p[x]->红。 root = rb_rotate_left(parent, root); //再对p[x]做一次左旋 other = parent->right; //x的新兄弟new w 是旋转之前w的某个孩子。其实就是左旋后的效果。 } if ((!other->left || other->left->color == BLACK) && (!other->right || other->right->color == BLACK)) //情况2:x的兄弟w是黑色,且w的俩个孩子也都是黑色的 { //由于w和w的俩个孩子都是黑色的,则在x和w上得去掉一黑色, other->color = RED; //于是,兄弟w变为红色。 node = parent; //p[x]为新结点x parent = node->parent; //x<-p[x] } else //情况3:x的兄弟w是黑色的, { //且,w的左孩子是红色,右孩子为黑色。 if (!other->right || other->right->color == BLACK) { if ((o_left = other->left)) //w和其左孩子left[w],颜色交换。 { o_left->color = BLACK; //w的左孩子变为由黑->红色 } other->color = RED; //w由黑->红 root = rb_rotate_right(other, root); //再对w进行右旋,从而红黑性质恢复。 other = parent->right; //变化后的,父结点的右孩子,作为新的兄弟结点w。 } //情况4:x的兄弟w是黑色的 other->color = parent->color; //把兄弟节点染成当前节点父节点的颜色。 parent->color = BLACK; //把当前节点父节点染成黑色 if (other->right) //且w的右孩子是红 { other->right->color = BLACK; //兄弟节点w右孩子染成黑色 } root = rb_rotate_left(parent, root); //并再做一次左旋 node = root; //并把x置为根。 break; } } //下述情况与上述情况,原理一致。分析略。 else { other = parent->left; if (other->color == RED) { other->color = BLACK; parent->color = RED; root = rb_rotate_right(parent, root); other = parent->left; } if ((!other->left || other->left->color == BLACK) && (!other->right || other->right->color == BLACK)) { other->color = RED; node = parent; parent = node->parent; } else { if (!other->left || other->left->color == BLACK) { if ((o_right = other->right)) { o_right->color = BLACK; } other->color = RED; root = rb_rotate_left(other, root); other = parent->left; } other->color = parent->color; parent->color = BLACK; if (other->left) { other->left->color = BLACK; } root = rb_rotate_right(parent, root); node = root; break; } } } if (node) { node->color = BLACK; //最后将node[上述步骤置为了根结点],改为黑色。 } return root; //返回root }
//五、红黑树的3种插入情况 //接下来,咱们重点分析针对红黑树插入的3种情况,而进行的修复工作。 //-------------------------------------------------------------- //红黑树修复插入的3种情况 //为了在下面的注释中表示方便,也为了让下述代码与我的倆篇文章相对应, //用z表示当前结点,p[z]表示父母、p[p[z]]表示祖父、y表示叔叔。 //-------------------------------------------------------------- rb_node_t* rb_insert_fixup(rb_node_t *node, rb_node_t *root) { rb_node_t *parent, *gparent, *uncle, *tmp; //父母p[z]、祖父p[p[z]]、叔叔y、临时结点*tmp while ((parent = node->parent) && parent->color == RED) { //parent 为node的父母,且当父母的颜色为红时 gparent = parent->parent; //gparent为祖父 if (parent == gparent->left) //当祖父的左孩子即为父母时。 //其实上述几行语句,无非就是理顺孩子、父母、祖父的关系。:D。 { uncle = gparent->right; //定义叔叔的概念,叔叔y就是父母的右孩子。 if (uncle && uncle->color == RED) //情况1:z的叔叔y是红色的 { uncle->color = BLACK; //将叔叔结点y着为黑色 parent->color = BLACK; //z的父母p[z]也着为黑色。解决z,p[z]都是红色的问题。 gparent->color = RED; node = gparent; //将祖父当做新增结点z,指针z上移俩层,且着为红色。 //上述情况1中,只考虑了z作为父母的右孩子的情况。 } else //情况2:z的叔叔y是黑色的, { if (parent->right == node) //且z为右孩子 { root = rb_rotate_left(parent, root); //左旋[结点z,与父母结点] tmp = parent; parent = node; node = tmp; //parent与node 互换角色 } //情况3:z的叔叔y是黑色的,此时z成为了左孩子。 //注意,1:情况3是由上述情况2变化而来的。 //......2:z的叔叔总是黑色的,否则就是情况1了。 parent->color = BLACK; //z的父母p[z]着为黑色 gparent->color = RED; //原祖父结点着为红色 root = rb_rotate_right(gparent, root); //右旋[结点z,与祖父结点] } } else { // if (parent == gparent->right) 当祖父的右孩子即为父母时。(解释请看本文评论下第23楼,同时,感谢SupremeHover指正!) uncle = gparent->left; //祖父的左孩子作为叔叔结点。[原理还是与上部分一样的] if (uncle && uncle->color == RED) //情况1:z的叔叔y是红色的 { uncle->color = BLACK; parent->color = BLACK; gparent->color = RED; node = gparent; //同上。 } else //情况2:z的叔叔y是黑色的, { if (parent->left == node) //且z为左孩子 { root = rb_rotate_right(parent, root); //以结点parent、root右旋 tmp = parent; parent = node; node = tmp; //parent与node 互换角色 } //经过情况2的变化,成为了情况3. parent->color = BLACK; gparent->color = RED; root = rb_rotate_left(gparent, root); //以结点gparent和root左旋 } } } root->color = BLACK; //根结点,不论怎样,都得置为黑色。 return root; //返回根结点。 }
void rb_insert_color(struct rb_node* node, struct rb_root* root) { int _switch = 1; struct rb_node *g_node, *u_node; while (_switch) { /* Sets Helper Nodes * g_node is so-called "grandparent" node of node * u_node is so-called "uncle" node of node * */ g_node = ((node != NULL) && (node->rb_parent != NULL)) ? \ node->rb_parent->rb_parent \ : NULL; u_node = (g_node != NULL) ? \ ((node->rb_parent == g_node->rb_left) ? g_node->rb_right : g_node->rb_left) \ : NULL; switch (_switch) { case 1: if (node->rb_parent == NULL) { node->color = BLACK; _switch = 0; break; } case 2: if (node->rb_parent->color == BLACK) { node->color = RED; _switch = 0; break; } case 3: if ((u_node != NULL) && (u_node->color != RED)) { node->rb_parent->color = BLACK; u_node->color = BLACK; g_node->color = RED; _switch = 1; node = g_node; break; } case 4: if ((node == node->rb_parent->rb_right) && (node->rb_parent == g_node->rb_left)) { rb_rotate_left(root, node->rb_parent); node = node->rb_left; } else if ((node == node->rb_parent->rb_left) && (node->rb_parent = g_node->rb_right)) { rb_rotate_right(root, node->rb_parent); node = node->rb_right; } _switch = 5; break; case 5: node->rb_parent->color = BLACK; g_node->color = RED; if (node == node->rb_parent->rb_left) rb_rotate_right(root, g_node); else rb_rotate_left(root, g_node); default: _switch = 0; break; } } }
void rb_erase(struct rb_node *node, struct rb_root* root) { struct rb_node *t_node, *tp_node; struct rb_node *s_node, *c_node; int _switch = 1; if ((node->rb_left != NULL)&&(node->rb_right != NULL)) { for (t_node = node; t_node->rb_right != NULL; t_node = t_node->rb_right); tp_node = t_node->rb_parent; rb_replace_node (root, node, t_node); tp_node->rb_right = node; node->rb_parent = tp_node; tp_node = t_node->rb_left; t_node->rb_left = node->rb_left; t_node->rb_right = node->rb_right; node->rb_left = tp_node; node->rb_right = NULL; } c_node = (node->rb_right == NULL) ? node->rb_left: node->rb_right; t_node = node; if (node->color == BLACK) { node->color = c_node->color; while (_switch) { s_node = (node->rb_parent != NULL) ? \ ((node->rb_parent->rb_left == node) ? node->rb_parent->rb_right : node->rb_parent->rb_left) \ : NULL; switch(_switch) { case 1: if (node->rb_parent == NULL) { _switch = 0; break; } case 2: if (s_node->color == RED) { node->rb_parent->color = RED; s_node->color = BLACK; if (node == node->rb_parent->rb_left) rb_rotate_left(root, node->rb_parent); else rb_rotate_right(root, node->rb_parent); _switch = 0; break; } case 3: if ((node->rb_parent->color == BLACK) && \ (s_node->color == BLACK) && \ (s_node->rb_left->color == BLACK) && \ (s_node->rb_right->color == BLACK)) { s_node->color = RED; _switch = 1; node = node->rb_parent; break; } case 4: if ((node->rb_parent->color == RED) && \ (s_node->color == BLACK) && \ (s_node->rb_left->color == BLACK) && \ (s_node->rb_right->color == BLACK)) { s_node->color = RED; node->rb_parent->color = BLACK; _switch = 0; break; } case 5: if (s_node->color == BLACK) { if ((node == node->rb_parent->rb_left) && \ (s_node->rb_right->color == BLACK) && \ (s_node->rb_left->color == RED)) { s_node->color = RED; s_node->rb_left->color = BLACK; rb_rotate_right(root, s_node); } else if((node == node->rb_parent->rb_right) && \ (s_node->rb_left->color == BLACK) && \ (s_node->rb_right->color = RED)) { s_node->color = RED; s_node->rb_right->color = BLACK; rb_rotate_left(root, s_node); } _switch = 0; break; } case 6: s_node->color = node->rb_parent->color; node->rb_parent->color = BLACK; if (node == node->rb_parent->rb_left) { s_node->rb_right->color = BLACK; rb_rotate_left(root, node->rb_parent); } else { s_node->rb_left->color = BLACK; rb_rotate_right(root, node->rb_parent); } _switch = 0; break; default: _switch = 0; break; } } } rb_replace_node (root, t_node, c_node); }