红黑树(3) - 删除操作

目录

1.删除操作介绍

2.删除操作步骤

3.简单场景

4.复杂场景

4.1 孩子节点是double black

4.2 被删节点是double black节点或者是非根节点

4.2.1 兄弟节点是黑色且孩子至少一个红色

4.2.2 兄弟节点是黑色且两个孩子都是黑色

4.2.3 兄弟节点是红色

4.3 孩子节点是根节点


在本系列的前面两篇文章中,已经介绍了红黑树以及其插入操作。具体可参考下面两个链接:
《红黑树(1) - 介绍》
《红黑树(2) - 插入操作》

1.删除操作介绍

类似于插入操作,红黑树进行删除节点时,也使用重新着色以及旋转这两种方式,来维护它的属性。
在插入操作中,我们主要是依靠检测叔节点的颜色来决定哪种场景。在删除操作中,我们使用检测兄弟的颜色,来决定是哪种场景。
在插入操作中,最常见的违反红黑树属性的一种情况是存在两个连续的红色节点。而在删除操作中,常见的情况是,当删除节点是黑色时,会影响从根节点到叶子的黑色节点高度。违反红黑树的性质5。
删除的过程相对比较复杂。为了便于理解删除过程,我们将使用到"double black"的概念。当一个黑色节点被删除,并且被它的黑色孩子取代时,这个孩子就标记为double black。因此,主要的工作就变为了将这个double black转换为single black。

2.删除操作步骤

下面是详细的删除步骤。在以下的内容里,d或者deleter表示被删节点,c或者child表示将用于替换d的孩子节点。

执行标准的二叉搜索树的删除操作。
在删除过程中,如果deleter是叶子或者只有一个孩子,则操作比较简单,基本上直接删除就可以了。
而对于存在两个孩子的节点,可以先查找到deleter的中序遍历时的后继节点,用它的值替换掉deleter的值,然后再删除这个后继节点(中序遍历时的后续节点总是一个叶子或只有一个孩子)。
如下图所示。这样的话,我们只需要处理被删节点是叶子或只有一个孩子的这种情况。

上图中,被删节点deleter是50,则它的中序遍历后继节点是60。用后继节点的值替换deleter的值,然后删除60这个后继节点。

当然,在本步骤中,也可以选取前驱节点(即被删节点左子树最大值)进行替换。原理与后继节点相似。这里不再描述。

3.简单场景

简单场景:deleter或者child是红色

使用孩子节点child替换deleter,然后将其置为黑色。这样黑色高度维持不变。这是因为deleter和child不可能同时是红色,其中必定有一个为黑色。

本步骤会覆盖到下面的这4种场景。

对于deleter拥有两个孩子(两颗子树)的场景,如下面的两个图所示,可以采用第2节提供的方法,转换为处理叶子节点或单个孩子的场景。

4.复杂场景

复杂场景:deleter和child都是黑色(包括deleter是叶子)

4.1 孩子节点child是double black

此时,主要工作就是将这个double black转换为single black。
注意:当deleter是叶子时,则默认child为null节点并且为黑色。所以,如果删除的是黑色叶子,则也会引发double black操作。

上图中,在转换为了double black后,实际上已经变成了4.2.1.c 小节的场景。可以使用Right Right Case旋转方式。

最终,删除节点20后,这棵树调整为:

4.2 被删节点deleter是double black或者非根节点

在这种情况下,假设s或者sibling表示为deleter的兄弟节点,则存在下面这些场景。

4.2.1 兄弟节点是黑色且孩子至少一个红色

场景1:sibling是黑色,并且它的孩子中至少有一个是红色,则进行旋转

假设s的这个红色的孩子为r,则根据s和r的位置,可以分为4种情况。

a. Left Left Case (s是左孩子,且r是s的左孩子或者s的两个孩子都是红色)。这种情形与下面的Right Right Case正好相反。

b. Left Right Case (s是左孩子,且r是s的右孩子)。这种情形与下面的Right Left Case正好相反。

c. Right Right Case (s是右孩子,且r是s的右孩子或者s的两个孩子都是红色)。

d. Right Left Case (s是右孩子,且r是s的左孩子)。

4.2.2 兄弟节点是黑色且两个孩子都是黑色

场景2:sibling是黑色,并且它的两个孩子都是黑色(包括sibling是叶子)

这种情况下需要重新着色,并且:
a. 如果s的父节点是黑色,则做完删除操作后,还需要检测父节点。

b. 如果s的父节点是红色,则不需要再检测父节点,而是可以简单地将其设置为黑色(红色+double black = single black)。

4.2.3 兄弟节点是红色

sibling是红色,执行旋转操作,提升sibling,并且重新着色sibling以及它的父节点

此时新的兄弟节点总是黑色的(下图的节点25)。至此,已经将这棵树通过旋转,转换为了兄弟为黑色的这种场景,使用4.2.1或者4.2.2继续处理。这种情形可以分为两种情况。

a) Left Case (s是左孩子)。右旋转父节点p。

b) Right Case (s是右孩子). 左旋转父节点p。

4.3 孩子节点child是根节点

如果child是根节点,将其转换为single black然后返回(完全二叉树的黑色高度减1)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值