红黑树删除详细解读

红黑树(二):删除 - 知乎

红黑树的删除确实复杂。侯捷的那本《STL源码解析》都跳过了这一节。《算法导论》里倒是没有跳过,但是我认为讲得不是很好。今天我不自量力,也来挑战一下,看能不能讲清楚了。

如果需要删除的结点有两个孩子,我们的做法是找到这个结点的中序后继,将后继结点中的数据拷贝至待删除结点,然后删除后继结点。而后继结点必然最多只有一个子结点,这样我们就把删除两个孩子的结点转为删除一个孩子的结点。在删除的过程中,我们只关心树是否仍然保持红黑树的性质,数据是否组织正确,而不关心这个结点是最初要删除的结点还是我们从中复制出值的那个结点。

接下来,我们只讨论删除只有一个儿子的结点,如果它两个儿子都为空,即均为叶子,我们任意将其中一个看作它的儿子。这里,体现出来,在红黑树里特别指定叶子结点为NIL结点的作用,NIL结点经常可以充当正常结点使用以使得算法的表达更加容易。

如果我们删除一个红色结点,它的父亲和儿子一定是黑色的。所以我们可以简单的用它的黑色儿子替换它,并不会破坏属性2和3。通过被删除结点的所有路径只是少了一个红色结点,这样可以继续保证属性4。另一种简单情况是在被删除结点是黑色而它的儿子是红色的时候。如果只是去除这个黑色结点,用它的红色儿子顶替上来的话,会破坏属性4,但是如果我们重绘它的儿子为黑色,则曾经通过它的所有路径将通过它的黑色儿子,这样可以继续保持属性4。这是比较简单的两种情况,我们不再讨论。

现在,需要详细讨论的就是如果待删除结点和它的子结点都是黑色的时候,这种比较复杂的情况。有些参考资料上为了表达形式上的简洁,把要讨论的情况分成了四类或者五类,而我认为,把情况细分为六类是比较合理的,这样更利于理解。而且不同于其他的讲解的地方是,我在这里调整了这六种情况的排序。先讲解最简单的,最后讲最复杂的,而不是追求形式上完善,这一点希望读者能够理解。

先来约定涉及到的结点的名称。我们先用待删除结点的孩子代替待删除结点,并且记这个孩子为N,记它的新的父结点为P,它的兄弟结点,也就是父结点的另外一个孩子为S, 记S的左孩子为,记S的右孩子为。

情况一。N是新的根。在这种情况下,我们就做完了。我们从所有路径去除了一个黑色节点,而新根是黑色的,所有属性都保持着。

情况二。P为红色,S和S的两个孩子都是黑色的。将P置为黑色,S置为红色。这样,不经过N的路径上的黑色结点数目并没有发生变化,而经过N结点的路径上黑色结点的数目 增加了1,刚好添补了这条路径上删除的黑色结点。所以红黑树又重新达到了平衡。

情况三。S是黑色,S的右儿子是红色,而N是它父亲的左儿子。在这种情况下我们在N的父亲上做左旋转,这样S成为N的父亲和S的右儿子的父亲。我们接着交换N的父亲和S的颜色,并使S的右儿子为黑色。子树在它的根上的仍是同样的颜色,所以属性3 没有被违反。但是,N现在增加了一个黑色祖先: 要么N的父亲变成黑色,要么它是黑色而S被增加为一个黑色祖父。所以,通过N的路径都增加了一个黑色节点。此时,如果一个路径不 通过N,则有两种可能性:

  1. 它通过N 的新兄弟。那么它以前和现在都必定通过S 和N 的父亲,而它们只是交换了颜色。所以路径保持了同样数目的黑色节点。
  2. 它通过N 的新叔父,S 的右儿子。那么它以前通过S、S 的父亲和S的右儿子,但是现在只通过S,它被假定为它以前的父亲的颜色,和 S 的右儿子,它被从红色改变为黑色。合成效果是这个路径通过了同样数目的黑色节点。

在任何情况下,在这些路径上的黑色节点数目都没有改变。所以我们恢复了属性4。在示意图中的白色节点可以是红色或黑色,但是在变换前后都必须指定相同的颜色

情况四。S是黑色,S的左儿子是红色,S的右儿子是黑色,而N是它父亲的左儿子。在 这种情况下我们在S上做右旋转,这样S的左儿子成为S的父亲和N的新兄弟。我们接着交换S和它的新父亲的颜色。所有路径仍有同样数目的黑色节点,但是现在N有了一个右儿子是红色的黑色兄弟,所以我们进入了情况三。N和它的父亲都不受这个变换的影响。如图2.19

情况五。S是红色。在这种情况下我们在N的父亲上做左旋转,把红色兄弟转换成N的 祖父。我们接着对调N的父亲和祖父的颜色。尽管所有的路径仍然有相同数目的黑色节点,现在N有了一个黑色的兄弟和一个红色的父亲,所以我们可以接下去按二、三或四情况来处 理。N它的新兄弟SL是黑色,因为它未旋转前是红色S的一个儿子。

情况六。N的父亲、S和S的儿子都是黑色的。在这种情况下,我们简单的重绘S为红 色。结果是通过S的所有路径,它们就是以前不通过N的那些路径,都少了一个黑色节点。 因为删除N的初始的父亲使通过N的所有路径少了一个黑色节点,这使事情都平衡了起来。 但是,通过P的所有路径现在比不通过P的路径少了一个黑色节点,所以仍然违反属性3。要修正这个问题,我们要从情况一开始,在P上做重新平衡处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值