首先,我们第一个问到的问题就是:删除一个节点应该怎样删除?看下面的二叉查找树:
当我们想删除2这个节点时,会发现如果就简单的给删除,不知道是将1给连接到11后面还是将7连接到11的后面。当然可以将7连接上去,然后将1的做孩子连接到5节点,但是当1后面有左孩子时,我们是不是又要去找1为根的子树的最大值呢?而且将5连接上去那会不会造成树的极度不平衡呢?其实不考虑效率,这是一种可以的方法的。为了满足树的平衡性,我们一般是找2的后继,即在此树中4为2的后继。这样,我们只要简单的将4删除就行了。对于节点有个孩子节点为空或孩子节点都为空,那么我们只要简单的处理就行了。
下面来看红黑树的删除:
红黑树的删除,一个比较麻烦的地方就是删除一个黑节点后树的红黑性质得不到保持,从而要想办法将这种性质保存下来。下面来看看,删除一个黑节点后我们需要做什么调整。
首先,看下图
对于删除17,我们会采用推到后继节点的策略来进行删除节点:首先将17的后继节点19替换到17节点,当然此时红黑性质保持不变,变的只是关键字,此时我们删除下图key所指的关键字17。
对于删除后的图为:
此时关键字key指向的为红色节点为20.这样我们需要对20这个节点进行调整,因为我们发现它违反了红黑树的规定。此时,我们直接将20给调整为黑色就ok了。我们知道,删除的节点肯定有一个孩子节点是空的,那么当我们用孩子节点替换删除的节点时,如果孩子节点为红色,我们直接调整这个孩子节点为黑色就能够保持红黑树的性质。那么当我们删除节点后孩子节点为黑时,我们需要做哪些调整呢?且 有多少种情况我们需要调整呢?
先来看删除的节点在这个节点的父节点的左边。
情况1:key节点的兄弟w节点为黑色,w的两个子节点为黑色。
key所指的节点为我们删除后其孩子节点,即,节点已经删除且为黑色节点,而其孩子节点A替换上来后的图。此时,我们要认识到B->A->...这条链上是少了一个黑色节点的,这样有路径只要包含这个路径都会少一个黑色节点。如果我们将D变红,那么会违法第3条规则:红色节点的子节点都为黑色。但是我们可以将B变黑,这样就保持了红黑树的性质。对这个图我们是直接将B变黑就行了,但是对于下图我们却不能够:
即key的父节点也为黑,此时我们只要将B节点变为key节点就行了,然后向上传播循环处理。如果我们此时的B节点为根节点那该怎么办呢?其实,这种情况是不会出现的。
情况2:
key节点的兄弟w节点为黑色,w节点的右节点为红色。看似平衡了,其实你要想一想删除的节点为黑色节点,而替换的是黑色节点。即在B->A链路以后的链路中都会少一个黑色的节点。为了平衡,我们可以将E变黑,B变黑 ,然后对B进行一个左旋转;此时还应该考虑D节点的颜色:如果B为红,则D为红,如果B为黑则D为黑,即将B的颜色赋给D。
情况3:key节点的兄弟w节点为黑色,w节点的左子节点为红色,右子节点为黑色。
这种情况,让w的左节点和w的颜色互换,然后对w进行右旋。这样将情况转换成了2.
情况4:key节点的兄弟节点w为红色。
这种情况下,key节点的兄弟节点w为红色。这种情况下父节点B可定是黑色,c,e节点也肯定是黑色。则可以,将B变成红色,D变成黑色,然后对B进行左旋。
这样就将情况4变成情况1,2,3中的一种了,再次循环就行了。
其实,树节点的删除是在删除节点的父节点及其兄弟节点间进行调整。局部调整后就能够将树调整平衡。
下面是代码,结合红黑树的建立,可以组成红黑树的建立及节点删除。
// delete.
int RBT_delete_fix(RBT* T,Node *x)
{
if(T == NULL || (*T) == NULL || x == NULL)
{
return 0 ;
}
while(x != (*T) && x->color == BLACK)
{
if(x == x->parent->left) // x is parent left child.
{
Node *parent = x->parent;
COLOR bc = BLACK ;
if(parent->right != NULL)
{
bc = parent->right->color ;
}
if(bc == RED)//case 4 brother is red.
{//the parent must be black.
parent->color = RED;
parent->right->color = BLACK ;
LEFT_ROATE(T,parent);
}else{//case 2 3 4 brother is black. 1 else
COLOR blc = BLACK ;
COLOR brc = BLACK ;
if(parent->right->left != NULL)
{
blc = parent->right->left->color ;
}
if(parent->right->right != NULL)
{
brc = parent->right->right->color ;
}
if(blc == BLACK && brc == BLACK)//CASE 1
{
parent->right->color = RED;
x = parent ;
}else
{
if(blc == RED && brc == BLACK)// case 3
{
parent->right->color = RED ;
parent->right->left->color = BLACK ;
RIGHT_ROATE(T,parent->right);
}
//case 2
parent->right->right->color = BLACK ;
parent->right->color = parent->color;
parent->color = BLACK ;
LEFT_ROATE(T,parent);
x = (*T); // break the while.
}
}// 1 else
}else{// x is parent right child.
Node *parent = x->parent;
COLOR bc = BLACK ;
if(parent->left != NULL)
{
bc = parent->left->color ;
}
if(bc == RED)//case 4 brother is red.
{//the parent must be black.
parent->color = RED;
parent->left->color = BLACK ;
LEFT_ROATE(T,parent);
}else{//case 2 3 4 brother is black. 1 else
COLOR blc = BLACK ;
COLOR brc = BLACK ;
if(parent->left->left != NULL)
{
blc = parent->left->left->color ;
}
if(parent->left->right != NULL)
{
brc = parent->left->right->color ;
}
if(blc == BLACK && brc == BLACK)//CASE 1
{
parent->left->color = RED;
x = parent ;
}else
{
if(blc == BLACK && brc == RED)// case 3
{
parent->left->color = RED ;
parent->left->left->color = BLACK ;
LEFT_ROATE(T,parent->left);
}
//case 2
parent->left->right->color = BLACK ;
parent->left->color = parent->color;
parent->color = BLACK ;
RIGHT_ROATE(T,parent);
x = (*T); // break the while.
}
}// 1 else
}
}//end while
x->color = BLACK ;
}
Node * treeSuccessor(Node *x)
{
if(x == NULL || x->right == NULL || x->left == NULL )
{
return NULL ;
}
Node *cur = x->right ;
//x = cur ;
while(cur != NULL)
{
x = cur ;
cur = cur->left ;
}
return x ;
}
int RBT_delete(RBT *T,int key)
{
if(T == NULL || (*T) == NULL )
{
return 0 ;// error .
}
Node *root = *T ;
Node *cur = root ;
// find the key .
while(cur != NULL)
{
if(cur->key == key)
{
break ;
}
if(cur->key > key )
{
cur = cur->left ;
}else
{
cur = cur->right ;
}
}
if(cur == NULL )
{
return 0 ;// not find key .
}
Node *y = cur ;
if(cur->right != NULL && cur -> left != NULL)
{// find the
y = treeSuccessor(cur);
}
// 删除
if(y != cur )
{
cur->key = y->key ;//125489
}
Node *parent = y->parent ;
Node *x = NULL ;
if(y->left != NULL)
{
x = y->left ;
}else
{
x = y->right ;
}
if(x != NULL )
{
x->parent = parent ;
if(parent != NULL)
{
if(y == parent->left)
{
parent->left = x ;
}else
{
parent ->right = x ;
}
}else// y is root .
{
(*T) = x ;
}
if(y->color == BLACK)
{
RBT_delete_fix(T,x);
}
delete y ;
}else
{// x is null .
x = new Node ;
x->parent = parent ;
x->color = BLACK ;
if(parent == NULL)// root is only.
{
(*T) = NULL ;
delete y ;
delete x ;
return 1 ;
}
if(y == parent->left)
{
parent ->left = x ;
}else
{
parent->right = x ;
}
if(y ->color == BLACK)
{
RBT_delete_fix(T,x);
}
parent = x->parent ;
if(x == parent->left)
{
parent->left = NULL ;
}else
{
parent->right = NULL ;
}
delete y ;
delete x ;
}
return 1 ;
}