红黑树的删除之3(共四篇)

本文详细解析了红黑树的删除操作,分为四种基本情形,并介绍了如何通过调整维持红黑树的平衡特性。针对每种情况,提供了具体的调整策略及伪代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  红黑树的删除操作是红黑树最复杂的操作了,只要搞明白这个,基本上就明白红黑树的调整。删除的情况大致可以分为四种。

case 1. .删除节点z,,子节点少于两个时,左儿子为T.NIL,用右儿子代替z

case 2. 删除节点z,子节点少于两个时,右儿子为T.NIL,用左儿子代替z

case 3 删除节点z,有两个子节点时,找出后继节点y,如果后继节点y是右儿子,直接用y子树替换z节点

case 4删除节点z,有两个子节点时,找出后继节点y,如果后继节点不是右儿子,用后继节点的右儿子x子树替换y子树,再用后继节点y子树替换z节点。

下面看看图形展示这四种删除情况,其中z节点表示想要删除的节点,y节点表示真正删除的节点(从删除节点的颜色角度来看),x表示要替换y的节点。由于y的颜色可能改变,用y-original-color表示y颜色改变之前的颜色

伪代码如下:

RB-DELETE(T, z)
  y = z;
  y-original-color = y.color;
  if z.left == T.NIL
    x = z.right;
    RB-TRANSPLANT(T, z, z.right);
  else if z.right == T.NIL
    x = z.left;
    RB-TRANSPLANT(T, z, z.left);
  else y = TREE-MINMUM(z.right)
    y-original-color = y.color;
    x = y.right;
    if y.p = z;
      x.p = y;
    else RB-TRANSPLANT(T, y, y.right)
         y.right = z.right; 
         y.right.p = y;
    RB-TRANSPLANT(T, z, y)
    y.left = z.left;
    y.left.p = y;
    y.color = z.color;
  if y-original-color == black
    RB-DELETE-FIXUP(T, x)

 

  可以看到,如果y是黑色的,就肯定破坏了红黑树的性质了。如果y是红色的,红黑树性质依然保持,因为树的黑高没有改变,也不存在两个相邻的的红色节点,性质4和5没有任何改变。所以y是黑色的时候需要通过RB-DELETE-FIXUP来调整修正。下面来看看如何调整。

 违反性质2的情况:如果y是原来的根节点,而y的一个红色孩子成为新的根几点,就违反了性质2,但是这很容易解决,直接染黑就是了,不再继续讨论这种情况。

 违反性质4的情况:x节点为红色,x的父节点也为红色,这种情况也很容易解决,染黑x就是了。

 剩下的情况就是只违反了性质5,只要调整好性质5就好了,这里有一个技巧,就是把x节点视为还有一层黑色,问题就变成了解决违反性质1了,也就是把x看成既红又黑,我们只要把这层额外的黑色不断往上推,直到推给了一个红色节点,那么子树的黑高就恢复了。和插入一样,有个关键思想是,转换过程中千万不能破坏其他任何的性质。经过分析,破坏性质1(本质上是破坏性质5)有以下五种情况:

  case 1 x是红色的

  case 2. x的兄弟节点w是红色的

  case 3 x的兄弟节点w是黑色的,而且w的两个子节点都是黑色的

  case 4 x的兄弟节点w是黑色的,w的左儿子是红色的,w的右孩子是黑色的

 case 5  x的兄弟节点w是黑色的,且w的右孩子是红色的。

如下图所示:

case 1是最容易解决的,直接染黑就是了。

case 2的话,改变w和x.p的颜色,左旋转x.p,这样子不改变任何性质的同时,把case 2转变为case 3,4,5。不做详细讨论

伪代码为:

 

w.color = black;
x.p.color = red;
LEFT-ROTATE(T, x.p)
w = x.p.right;

 

 

 

case 3的话,可以认为从x和w去掉一层黑色给x.p,如果x.p为原本为红色的话,那么x的子树黑高加一,w子树黑高不变,性质就恢复好了,如果x.p原来为黑色的,那么认为x.p的整个子树黑高都少了1,多了的一层黑色就给了x.p,case3就转为case 2,3,4,5了。

伪代码如下:

 

  w.color = red;
  x = x.p


case 4的情况左侄儿为红,右侄儿为黑,这种情况统一转case 5来处理。

 

这里右旋w并且没有改变红黑树的五大性质,转为了case5。伪代码如下:

 

w.left.color = black;
w.color = red;
RIGHT-ROTATE(T, w)
w = x.p.right;


case 5的情况是红黑树调整的出口,只要到达了case 5,调整完就能恢复所有性质了。调整如下图所示:

 

接下来分析case5的转换过程,这里的思路是这样的:首先我们要让x子树黑高加一,那么就左旋转a,左旋转后d的左子树没有任何问题,但是右子树黑高可能减少了1(如果a原来是黑色的情况),为了解决这个问题,可以把a和d颜色交换,然后染黑c,这样左旋转后的d的右子树的黑高也就不会有任何改变了。伪代码如下:

 

w.color = x.p.color;
x.p.color = black;
w.right.color = black;
LEFT-ROTATE(T, x.p);
x = T.root;

 

 

 

为了能在全局下看到调整情况,下面展示整个删除调整的过程伪代码:

 

RB-DELETE-FIXUP(T, x)
 while x != T.root && x.color = black
   if x == x.p.left
     w = x.p.right
     // case 2
     if w.color = red
       w.color = black;
       x.p.color = red;
       LEFT-ROTATE(T, x.p)
       w = x.p.right;
     // case 3
     if w.left.color == black && w.right.color == black
       w.color = red;
       x = x.p;
     // case 4
     else if w.right.color == black
       w.left.color = black;
       w.color = red;
       RIGHT-ROTATE(T, w)
       w = x.p.right;
     // case 5
     w.color = x.p.color;
     x.p.color = black;
     w.right.color = black;
     LEFT-ROTATE(T, x.p);
     x = T.root;

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值