算法分析
删除z节点(假设要删除z节点):
case1:z为叶子时,删除z后,直接将z的叶子节点连接到z的父节点。
case2:z只有一个孩子(非空)时,删除z后,将z的非空孩子直接连接到z的父节点。如图1所示。
图1.删除case2
case3:z的两个孩子均为非空,此时首先找z的中序后继,即找z的右子树中最左下节点y;然后删除y,将y的内容copy到z中,再将y的右子树连到y的父节点左下。
如图2所示。
图2.删除case3
以上三种情况,删除红点不影响,删除黑点需要维护。
维护算法:
假设x是y的唯一孩子或者是叶子节点。将y(对于删除case1和case2为z)的黑色涂到x上(先不管x的颜色)。于是,
若x为红,只要将其涂黑,维护即可终止;
若x为黑,将y的黑色涂上之后,x则是一个双黑节点,违反了红黑树性质1。
处理步骤:
- 若x为根,直接移去多余的一层黑色(树黑高减一),终止;
- 若x为红,将y的黑色涂到x上,终止;
- 若x为非根节点,且为黑色,则将y的黑色涂到x上,x变为双黑。通过变色,旋转,使多余的黑色向上传播,直到某个红色节点或传到根。
对于上边第三个步骤,x变为双黑后,分情况进行讨论维护,根据x是其父节点的左右孩子,分为8中情况,这里讨论x是其父节点的左孩子的4种情况。
以下所有情况中R代
表红,B代表黑。
case1:x的兄弟w为红色。如图3所示。
图3.维护case1
case2:x的黑兄弟w的两个孩子均为黑。如图4所示。
图4.维护case2
case3:x的黑兄弟w的右子为黑,左子为红。如图5所示。
图5.维护case3
case4:x的黑兄弟w的右子为红,左子为黑或红,如图6所示。
图6.维护case4
算法实现(C语言)
定义的数据结构:
typedef struct RBTNode
{
int key;
struct RBTNode *parent,*left,*right;
int color;
//int size;
}RBTNode,*RBTree;
删除算法:
void RBTreeDelete(RBTree z)
{
RBTree x,y;
if(z->left == nil || z->right == nil)
y = z;
else
y=TreeSuccessor(z); //y为z的中序后继
if(y->left != nil)
x = y->left;
else
x = y->right;
x->parent = y->parent;
if(y->parent == nil)
root = x;
else
{
if(y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
}
if(y != z)
z->key = y->key;
if(y->color == BLACK)
RBTreeDeleteFixup(x);
free(y); //VC6.0下这句好像有问题,可注释掉。
}
删除后维护:
void RBTreeDeleteFixup(RBTree x)
{
RBTree w;
while(x != root && x->color == BLACK){
if(x == x->parent->left){
w = x->parent->right;
if(w->color == RED){ //case 1
w->color = BLACK;
x->parent->color = RED;
LeftRotate(x->parent);
w = x->parent->right;
}
if(w->left->color == BLACK && w->right->color == BLACK){ //case 2
w->color = RED;
x = x->parent;
}
else{
if(w->right->color == BLACK){ //case 3
w->left->color = BLACK;
w->color = RED;
RightRotate(w);
w = x->parent->right;
}
w->color = x->parent->color; //case 4
x->parent->color = BLACK;
w->right->color = BLACK;
LeftRotate(x->parent);
x = root;
}
}
else{
w = x->parent->left;
if(w->color == RED){
w->color = BLACK;
x->parent->color = RED;
RightRotate(x->parent);
w = x->parent->left;
}
if(w->left->color == BLACK && w->right->color == BLACK){
w->color = RED;
x = x->parent;
}
else{
if(w->right->color == BLACK){
w->left->color = BLACK;
w->color = RED;
LeftRotate(w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
RightRotate(x->parent);
x = root;
}
}
} //endwhile
x->color = BLACK;
}
查找z的中序后继:
RBTree TreeSuccessor(RBTree z)
{
RBTree x;
x = z->right;
while(x->left != nil)
x = x->left;
return x;
}
最后,对于想验证一下,可以参考我的上篇博客: 建立红黑树(左旋、右旋、插入、维护)代码+验证,谢谢!