必须要把红黑树讲清楚,看完还不明白请直接找我之3(共四篇)—红黑树的删除

来源:互联网 发布:linux怎么保存文件 编辑:程序博客网 时间:2024/05/16 19:53

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

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;


0 0
原创粉丝点击