算法导论第十三章:红黑树下之删除分析

与n个节点的红黑树上的其他操作一样,删除一个节点要花费O(lgn)时间,但与插入操作相比,删除操作要稍微复杂一点。

如果被删除节点是红色的,红黑性质将继续保持,但如果被删除节点是黑色的话,就有可能发生一个或多个红黑性质被破坏的情况。

其核心在于,进行删除操作后的红黑树如果不符合其性质,我们如何进行调节。

下面结合伪代码进行讲解:

RB-TRANSPLANT方法将节点v替换u节点的位置

RB-TRANSPLANT(T,u,v)   //T为树,u,v为节点
if u.p==T.nil          //如果u的父节点等于哨兵(哑节点,可以看作空)
   T.root=v               //树T的根节点设为v
else if u==u.p.left    //否则如果u是其父节点的左孩子
        u.p.left=v        //将其父节点的左孩子换为v
else u.p.right=v       //否则将其父节点的右孩子换为v
v.p=u.p                //v的父节点改为u的父节点

RB-DELETE()方法用于执行红黑树的删除操作:

RB-DELETE(T,z)                  //T为树,z为删除节点
y=z
y-original-color=y.color       //记住y的原始颜色
if z.left==T.nil               //如果z节点的左孩子为空
   x=z.right                   //x就为z的右孩子
   RB-TRANSPLANT(T,z,z.right)  //将z节点的右孩子替换z
else if z.right==T.nil         //否则如果z节点的右孩子为空
        x=z.left               //x为z的左孩子
        RB-TRANSPLANT(T,z,z.left)//将z节点的左孩子替换z
else  y=TREE-MINIMUM(z.right)    //否则y等于z右子树的最小节点
      y-original-color=y.color   //记录y的原始颜色
      x=y.right                  //x等于y的右孩子
      if y.p==z                  //如果z是y的父节点
         x.p=y                   //将x的父节点设为y
      else RB-TRANSPLANT(T,y,y.right)//否则将y的右孩子替换y
           y.right=z.right           //z的右孩子给y
           y.right.p=y               
      RB-TRANSPLANT(T,z,y)           //y替换z的位置
      y.left=z.left                  //z的左孩子给y
      y.left.p=y
      y.color=z.color                //z的颜色给y
if y-original-color==black           //如果z右子树的最小节点是黑色的
   RB-DELETE-FIXUP(T,x)              //修复红黑树

RB-DELETE-FIXUP()方法如下:

RB-DELETE-FIXUP(T,x)
while x!=T.root &&x.color==black  //当x不为根节点且x为黑色时
     if x==x.p.left               //如果x为左孩子
        w=x.p.right               //w等于x的兄弟节点
        if w.color==red           //如果w为红色
           w.color=black          //将w变为黑色
           x.p.color=red          //x的父节点变为红色
           LEFT-ROTATE(T,x.p)     //将x的父节点向左旋转
           w=x.p.right            //w为x父节点的右孩子
        if w.left.color==black&&w.right.color==black  //如果w左右孩子都为黑色
          w.color=red                       //将w染成红色
          x=x.p                             //x替换其父节点
        else if w.right.color==black       //否则如果w的右孩子为黑色
                 w.left.color=black       //将w的左孩子染成黑色
                 w.color=red              //将w染成红色
                 RIGHT-ROTATE(T,w)        //将w向右旋转
                 w=x.p.right              //w设为x的兄弟节点
           w.color=x.p.color              //否则w的颜色设为和x父节点一样
           x.p.color=black                //x父节点的颜色设为黑色
           w.right.color=black            //w的右孩子设为黑色
           LEFT-ROTATE(T,x.p)             //将x父节点向左旋转
           x=T.root                      //x设为树的根节点
      else(same as then clause with "right" and "left" exchanged)//否则在前面的基础上交换left和right
   x.color=black//将x的颜色设为黑色

通过上面的代码我们可以看出调节过程有四种情况:

情况1:x的兄弟节点w是红色的

情况2:x的兄弟节点w是黑色且w的两个孩子都为黑色

情况3:x的兄弟节点w是黑色且w的左孩子为红色,右孩子是黑色

情况4:x的兄弟节点w是黑色且w的右孩子是红色的

针对者四种情况有不同的处理方案,可以跟随上面代码自己画一颗树操作来进行理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小牧之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值