<pre name="code" class="cpp">c语言代码:基本引用或模仿自http://blog.youkuaiyun.com/chenhuajie123/article/details/11951777,还有个人的一点补充
//删除节点修复,关键在于双层色(额外黑色)恢复成单层
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; //x的兄弟*other,兄弟左孩子*o_left,*o_right
while ((!node || node->color == BLACK) && node != root)
{
if (parent->left == node)
{
other = parent->right;
if (other->color == RED) //Case1: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))
//Case2:x的兄弟w是黑色,且w的两个孩子也都是黑色的
{ //由于w和w的俩个孩子都是黑色的,则在x和w上得去掉一黑色,
other->color = RED; //于是,兄弟w变为红色。
node = parent; //p[x]为新结点x
parent = node->parent; //x<-p[x]
}
else //Case3: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是黑色的,且w的右孩子是红
other->color = parent->color; //把兄弟节点染成当前节点父节点的颜色。
parent->color = BLACK; //把当前节点父节点染成黑色
//---------------------------------------------------------------------
//1.父节点原本为红色,染为黑,左右子树黑高+1
//兄弟节点黑转红,兄弟节点右孩子红转黑,左旋,右子树黑高平衡
//左子树多了原本父节点的黑色,黑高+1,平衡额外黑色
//2.父节点原本为黑色,左旋后
//左子树多了原本兄弟节点的黑色,平衡额外黑色
//右子树少了原本父节点的黑色,加上原本兄弟节点的右孩子红转黑,平衡
//---------------------------------------------------------------------
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;
}
}
}
//1.维持了每个节点或红或黑,且2.红节点的子节点为黑的性质,3.叶子结点为黑色NIL本来就不变
if (node)
{
node->color = BLACK; //最后将node[上述步骤置为了根结点],改为黑色。因为可能导致root为红,此时root的子节点必然为黑,所以root红转黑后,4.根节点为黑,且5.两端黑高都+1,平衡
}
return root; //返回root
} <pre name="code" class="cpp">static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root){
//插入节点要记得考虑头尾
while((node->parent != NULL) && (node->parent->color == RED))//破坏性质:红节点子节点为黑,同时可知爷爷为黑
{
if(node->parent == node->parent->parent->left){
//Case1:node的叔节点为红
if((node->parent->parent->right != NULL) && (node->parent->parent->right->color == RED)){
node->parent->parent->color = RED;//爷爷黑转红,黑高-1
//父和叔红转黑,黑高+1 --->平衡
node->parent->color = BLACK;//父红转黑
node->parent->parent->right->color = BLACK;//叔红转黑;
node = node->parent->parent;
}
else{
//node为右子节点
//因为爷爷要黑转红,那么爷爷的子节点要为黑,而此时右子节点为node红
if(node == node->parent->right)
{
node = node->parent;
root = rb_rotate_left(node, root);//
//左旋不改变黑高
//使得父为原来的node红,node节点的右子节点自然为黑,满足条件
}
node->parent->color = BLACK;//父红转黑,黑高+1
node->parent->parent->color = RED;//爷爷黑转红,黑高-1,左子树平衡,但右子树黑高-1
root = rb_rotate_right(node->parent->parent, root); //右旋使得左子树父节点为爷爷,右子树黑高+1-->平衡
}
}
else//镜像
{
if((node->parent->parent->left != NULL) && (node->parent->parent->left->color == RED)){
node->parent->parent->color = RED;
node->parent->color = BLACK;
node->parent->parent->left->color = BLACK;
node = node->parent->parent;
}else{
if(node == node->parent->left){
node = node->parent;
root = rb_rotate_right(node, root);
}
node->parent->color = BLACK;
node->parent->parent->color = RED;
root = rb_rotate_left(node->parent->parent, root);
}
}
}
root->color = BLACK;//如果插入的为第一个节点为root,要红转黑
return root;
}