红黑树的删除

红黑树的删除

普通二叉查找树的删除

我们知道红黑树树也是一种二叉查找树,那么普通的二叉查找树的删除必然是红黑树删除的基础。但是红黑树的删除要在普通删除的基础上进行相应的调整,因为红黑树有自己必须要满足的5种性质,普通的删除可能会破坏原本红黑树的一些性质,那么就需要进行相应的调整。那么我们首先来回顾一下普通的删除到底是怎么操作的。大致思路就是找到要删除的节点然后对它进行删除操作。 对于要删除的节点主要分为三种情况:

  1. 要删除的节点是叶子节点
  2. 要删除的节点只有一个孩子
  3. 要删除的节点有两个孩子

为了说明该怎么删除,我们不妨举个例子,如图1、5、7、13、15、16、19、23序列构成的一个二叉排序树如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LaV98ImT-1592669512046)(source2/删除举例.png)]

情况1

对于情况1而言,操作很简单,直接将它删除就好了。例如删除例子中的节点1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2TOQzVqF-1592669512048)(source2/删除叶子节点.png)]

情况2

对于情况2而言,实际删除的是要删除节点的后继节点而非要删除的节点,操作分为两步:

  1. 将其孩子节点,放到当前节点的位置
  2. 删除当前节点

就以删除例子中的节点7为例。在例子中节点7只有一个孩子就是节点5。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ho3UgP12-1592669512049)(source2/删除单亲节点.png)]

情况3

对于情况3而言,我们就去当前节点的后继节点。由于二叉排序树本身的性质,其后继节点一定满足情况1或者情况2。于是我们进行如下操作:

  1. 找到要删除节点的后继节点并将后继节点的内容写到要删除的节点上
  2. 对后继节点进行删除操作(情况1或是情况2)

以删除例子中的节点13为例。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SSBZb9mS-1592669512050)(source2/删除双子节点.png)]

红黑树的删除

对于红黑树而言,要删除一个节点就要在普通的二叉排序树的删除的基础上,然后对删除后的二叉树进行调整以满足红黑树的5种特性。我们先来回顾一下红黑树的5个特性:

  1. 每个节点或者是黑色、或者是红色。
  2. 根节点的颜色是黑色。
  3. 每个叶子节点是黑色。(这里的叶子节点是为空NIL的叶子节点)
  4. 如果节点是红色的,那么他的子节点必是黑色的。
  5. 从一个节点到该节点下的叶子节点的所有路径上包含相同数目的黑色节点
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eeTTBQLp-1592669512051)(source2/示例图.png)]

从之前我们回顾的二叉排序树的删除可以看出来,最后删除的节点肯定会是情况1和情况2。这里我们规定在情况1即删除的节点是叶子节点时,我们以一个空节点放到要删除节点的位置,这样情况1就变成了情况2。以下我们都是在删除的情况2的的基础上讨论。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3W6gRPgc-1592669512052)(source2/空.png)]

我们以被删除的节点的孩子节点(实际上就是顶替在被删除节点的位置的节点)为当前节点进行调整。我们任然为这些节点设置一些代号。

  • 被删除的节点是D。
  • 当前节点为N。
  • 当前节点N的父节点为F。
  • 当前节点N的兄弟节点为B。
  • B的左孩子为LB。
  • B的右孩子为RB。

**值得注意的是在删除操作中我们不将NIL看成是一个节点。**删除后的二叉树至少满足1和3两条特性。(这颗二叉树中的任意一个空指针都会志向一个NIL叶子)

首先我们讨论一下最终要删除的节点D对结果的影响进行讨论。

D是红色的

如果D是红色的,那么删除D以后特性4和特性5都不会被打破。这种情况下操作就变得特别容易,只需要调整使得特性2满足就行了。如果删除D以后N变成了根节点,那么只要将N设置为黑色就行了。如果N不是根节点,那么什么都不用做此时的二叉树任然是一个红黑树。

D是黑色的

如果D是黑色的,那么删除D以后特性4和特性5都会被打破,这时就比较麻烦,我们需要对删除后的二叉树进行一些调整使其任然是一颗红黑树。**为了方便之后的调整,我们做这样一件事情——允许N拥有额外的黑色(继承于D)。**这样我们就保证在调整的过程中始终满足特性5。同时由于N带有一个额外的黑色因此绝不会破坏特性4和特性2。也就是说通过此特殊处理此二叉树满足红黑树的所有特性,我们的任务就是消解这个额外的黑色。

下面是调整的流程图,其中具体的情况和操作请于之后的内容相对应。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UBZjtS8r-1592669512052)(source2/流程图.png)]

在讨论之前我需要对一下操作图中的一些符号进行解释:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yRD26QQs-1592669512053)(source2/说明.png)]

1、N是根节点

这时只要保留N上的黑色以满足特性2,就完成了调整。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jAnN46vO-1592669512054)(source2/根.png)]

2-1、N是红色的

同样,这时只要保留N上的黑色(特性2、4、5都不会被破坏),就能够完成调整。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aUDgWFsP-1592669512054)(source2/N红.png)]

2-2、N是黑色的

N的位置有两种情况,要么他是F的左孩子,要们就是F的右孩子。两种位置下的操作是相似的,只要理解一种情况的解决方法就能够很轻松的类比出另外一种的方法。下面我会用操作图的形式向大家说明。(我会在不同的情况后面加上左右以区分N相对于F为位置,大家可以先看N在F左边的情况再类比出N在F右边的情况)。

2-2-1左、N黑B红

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lStz6elo-1592669512055)(source2/case1.png)]
这种情况下操作的主要思想就是把N的兄弟B变成黑色,这样就变成了2-2-2~2-2-4所表示的情况,然后再进一步做调整

2-2-1右、N黑B红

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CrOW7RSw-1592669512055)(source2/case1右.png)]

2-2-2左、N黑B黑LB黑RB黑

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tbFJaD6H-1592669512056)(source2/case2.png)]
这种方法的思想就是将额外的黑色向上移动,然后以F为新的N重新进行调整。向上移动的过程中可能额外的黑色在中间的调整中就会被消解。如果在过程中都没有被消解,那么额外的黑色也会被传递到根节点从而被消解。

2-2-2右、N黑B黑LB黑RB黑

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ajODTk0z-1592669512056)(source2/case2右.png)]

2-2-3左、N黑B黑LB红RB黑

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NTpQhXTb-1592669512057)(source2/case3.png)]
这种情况下处理思想是将其转化为2-2-4的情况,然后再进一步调整。因为这种情况本身无法处理额外的黑色,需要对其做一定的转变。

2-2-3右、N黑B黑RB红LB黑

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bR5MLRfN-1592669512057)(source2/case3右.png)]

2-2-4左、N黑B黑RB红

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lz2xd6Lo-1592669512058)(source2/case4.png)]
这种情况的非常好的,因为只要做一些旋转和变色的操作就能够消解掉额外的黑色,调整也就完成了

2-2-4右、N黑B黑LB红

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ae1sEGj-1592669512058)(source2/case4右.png)]

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
红黑树删除操作相对比较复杂,需要考虑多种情况。下面是一个简单的红黑树删除的 Java 实现示例: ```java public class RedBlackTree { private Node root; // 其他代码... public void delete(int value) { Node node = search(root, value); if (node != null) { deleteNode(node); } } private void deleteNode(Node node) { Node y = node; Node x; boolean yOriginalColor = y.isBlack(); if (node.getLeft() == null) { x = node.getRight(); transplant(node, node.getRight()); } else if (node.getRight() == null) { x = node.getLeft(); transplant(node, node.getLeft()); } else { y = minimum(node.getRight()); yOriginalColor = y.isBlack(); x = y.getRight(); if (y.getParent() == node) { if (x != null) { x.setParent(y); } } else { transplant(y, y.getRight()); y.setRight(node.getRight()); y.getRight().setParent(y); } transplant(node, y); y.setLeft(node.getLeft()); y.getLeft().setParent(y); y.setColor(node.getColor()); } if (yOriginalColor) { deleteFixup(x); } } private void deleteFixup(Node x) { while (x != root && x.isBlack()) { if (x == x.getParent().getLeft()) { Node w = x.getParent().getRight(); if (!w.isBlack()) { w.setBlack(true); x.getParent().setBlack(false); leftRotate(x.getParent()); w = x.getParent().getRight(); } if (w.getLeft().isBlack() && w.getRight().isBlack()) { w.setBlack(false); x = x.getParent(); } else { if (w.getRight().isBlack()) { w.getLeft().setBlack(true); w.setBlack(false); rightRotate(w); w = x.getParent().getRight(); } w.setBlack(x.getParent().isBlack()); x.getParent().setBlack(true); w.getRight().setBlack(true); leftRotate(x.getParent()); x = root; } } else { Node w = x.getParent().getLeft(); if (!w.isBlack()) { w.setBlack(true); x.getParent().setBlack(false); rightRotate(x.getParent()); w = x.getParent().getLeft(); } if (w.getRight().isBlack() && w.getLeft().isBlack()) { w.setBlack(false); x = x.getParent(); } else { if (w.getLeft().isBlack()) { w.getRight().setBlack(true); w.setBlack(false); leftRotate(w); w = x.getParent().getLeft(); } w.setBlack(x.getParent().isBlack()); x.getParent().setBlack(true); w.getLeft().setBlack(true); rightRotate(x.getParent()); x = root; } } } x.setBlack(true); } // 其他辅助方法... } ``` 这只是一个简单的实现示例,更详细和完善的红黑树删除算法可以参考相关的算法书籍或网络资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值