红黑树的删除——C语言
昨天理解了红黑树的定义、插入,旋转(左旋右旋)及相关代码实现,今天继续红黑树的删除。
可以先进行总结的是:红黑树的删除也是分两步走——第一步:像一个普通二叉查找树一样删除结点;第二步:对删除后的树进行修正。具体操作如下:
1、第一步:像一个普通二叉查找树一样删除结点并根据被删除结点的颜色决定下一步该怎么做。
//(二叉查找树删除①当待删除结点有两个孩子的时候,找到右孩子的左叶子或左孩子的右叶子,替换删除;②当待删除结点一个孩子的时候,把它的孩子接在待删除结点父结点上再删除;③叶子结点直接删除)
·当被删除结点是红色时——不需要修正,删除操作结束;
·当被删除结点是黑色时——需要进行修正(见第二步)。
2、第二步:对删除后的树进行修正。
//待修正结点为N
·N兄弟为红,其它都为黑时——对N父亲左旋,父兄互换颜色;
·N兄弟为黑,且N兄弟为右时——
·若N兄弟左孩子为红,右孩子为黑——N兄弟右旋,N兄弟和N兄弟左孩子互换颜色;
·若N兄弟右孩子为红,左孩子任意——N父亲左旋,N兄弟和N父亲互换颜色,兄弟右孩子涂黑;
·若N兄弟左,右孩子都为黑——N的兄弟涂红,研究父节点。
·最后待修正结点不管什么颜色都涂黑。
删除结点代码实现:
//删除
void rbtree_delete(RBRoot *root,Node *node)
{
Node *temp,*child,*parent;//替换结点
int color;
//当node有俩孩子时
if((node->lchild!=NULL)&&(node->rchild!=NULL))
{
//找到待删除结点的后继结点,即右子树的最左边的叶子结点
temp=node->rchild;
parent=node->parent;
while(temp->lchild!=NULL)
{
temp=temp->lchild;
}
//判断待删除结点是否为根节点
if(node->parent!=NULL)
{//不为根
if(node==node->parent->lchild)
{
node->parent->lchild=temp;
}
else
{
node->parent->rchild=temp;
}
}
else
{//为根
root->node=temp;
}
parent=temp->parent;//parent标记temp父结点
//child是temp的右孩子,temp必然没有左孩子,必然要对child进行调整;
child=temp->rchild;
//判断temp是否为node的父节点
if(parent==node)
{//是,直接替代
parent=temp;
}
else
{//不是,调整
//child若存在,则设为parent的左孩子
if(child!=NULL)
{
child->parent=parent;
}
parent->lchild=child;
temp->rchild=node->rchild;
node->rchild->parent=temp;
}
temp->parent=node->parent;
temp->color=node->color;
temp->lchild=node->lchild;
node->lchild->parent=temp;
}
else
{//若只有1个孩子
if(node->lchild!=NULL)
{
child=node->lchild;
}
else
{
child=node->rchild;
}
parent=node->parent;
color=node->color;
if(child!=NULL)
{
child->parent=parent;
}
if(parent!=NULL)
{//node不为根时
if(parent->lchild==node)
{
parent->lchild=child;
}
else
{
parent->rchild=child;
}
}
else
{//node为根
root->node=child;
}
}
if(color==BLACK)
{
rbtree_delete_fixup(root, child, parent);
free(node);
return;
}
}
删除修正代码实现:
//删除修正
void rbtree_delete_fixup(RBRoot *root,Node *node,Node *parent)
{
Node *bro;
int color;
while((node!=root->node)&&(node->color!=BLACK||node==NULL))//当待调结点是根结点并且是黑色的或者是空的,就跳出循环
{
if(parent->lchild==node)
{//若待调结点是左孩子
br