红黑树(3) - 删除操作

原创 2015年07月11日 22:30:29
在本系列的前面两篇文章中,已经介绍了红黑树以及其插入操作。具体可参考下面两个链接:
红黑树(1) - 介绍
红黑树(2) - 插入操作

1.删除操作介绍

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

2.删除操作步骤

下面是详细的删除步骤。在以下的内容里,d表示被删节点,c表示将用于替换d的孩子节点
执行标准的二叉搜索树的删除操作。在删除过程中,如果d是叶子或者只有一个孩子,则操作比较简单,基本上直接删除就可以了。而对于存在两个孩子的节点,可以先查找到d的中序遍历时的后继节点,用它的值替换掉d的值,然后再删除这个后继节点(中序遍历时的后续节点总是一个叶子或只有一个孩子)。如下图所示。这样的话,我们只需要处理被删节点是叶子或只有一个孩子的这种情况。
              50                                            60                                        60
           /     \           delete(50)               /   \          delete(60')           /  \
        40     70    ----------------->      40    70 ------------------>   40   70
                 /  \      后继节点赋值                  /  \      删除后继节点               \
              60   80   给被删节点                  60'   80                                      80 
上图中,被删节点d是50,则它的中序遍历后继节点是60。用后继节点的值替换d的值,然后删除60这个后继节点。
当然,在本步骤中,也可以选取前驱节点(即被删节点左子树最大值)进行替换。原理与后继节点相似。这里不再描述。

3. 简单场景-d或者c是红色

使用孩子节点c替换d,然后将其置为黑色。这样黑色高度维持不变。这是因为d和c不可能同时是红色,其中必定有一个为黑色。
本步骤会覆盖到下面的这4种场景。
              30                            30
           /     \       delete(20)        /   \
          20      40    ------------->    10    40 
         /                                  
        10                          
              30                            30
           /     \       delete(10)        /   \
          10      40    ------------->    20    40 
            \                               
            20         
              30                            30
           /     \       delete(20)        /   \
          20      40    ------------->    10    40 
         /                                  
        10        
              30                            30
           /     \       delete(10)        /   \
          10      40    ------------->    20    40 
            \                                  
            20  
对于d拥有两个孩子(两颗子树)的场景,如下面的两个图所示,可以采用第2节提供的方法,转换为处理叶子节点或单个孩子的场景。
              40                                 40                                40
           /     \        delete(20)           /   \        delete(30')           /  \
          20      50 ---------------------->  30    50 --------------------->   30   50
         /  \          执行步骤2.1,将d的       /  \      此时转换为了删除叶子30'.   /
        10  30         后继节点的值赋给d.      10  30'                           10
              40                                 40                                40
           /     \        delete(20)           /   \        delete(30')           /  \
          20      50 ---------------------->  30    50 --------------------->   30   50
         /  \          执行步骤2.1,将d的       /  \      此时转换为了删除叶子30'.   /
        10  30         后继节点的值赋给d.      10  30'                           10

4. 复杂场景-d和c都是黑色(包括d是叶子)

4.1. 孩子节点c是double black

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

上图中,在转换为了double black后,实际上已经变成了4.2.1.c的场景。可以使用Right Right Case旋转方式。
最终,删除节点20后,这棵树调整为:
              30                            40
           /     \       delete(20)        /   \
          20      40    ------------->    30    50 
                    \                             
                     50               

4.2. d是double black,或者d不是根节点

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

4.2.1. s是黑色,并且s的孩子中至少有一个是红色,则进行旋转

假设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. s是黑色,并且s的两个孩子都是黑色(包括s是叶子)

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


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

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

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

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

红黑树、插入删除操作

二叉排序树 一棵自平衡的二叉排序树(二叉搜索树) 生成二叉排序树的过程是非常容易失衡的,最坏的情况就是一边倒(只有右/左子树),这样会导致二叉树的检索效率大大降低(O(n))。 为了维...
  • zly9923218
  • zly9923218
  • 2016年04月01日 13:41
  • 1127

红黑树之删除操作

转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7760584       算法导论书上给出的红黑树的性质如下,跟STL源...
  • u010367506
  • u010367506
  • 2014年04月17日 21:35
  • 1146

红黑树插入删除操作

R-B Tree简介     R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(...
  • justdoithai
  • justdoithai
  • 2016年09月26日 15:42
  • 416

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

红黑树的删除操作是红黑树最复杂的操作了,只要搞明白这个,基本上就明白红黑树的调整。RB-DELETE(T, z) y = z; y-original-color = y.color; if...
  • lm2009200
  • lm2009200
  • 2017年04月13日 22:27
  • 310

极易理解的红黑树讲解

原文链接:http://www.cnblogs.com/abatei/archive/2008/12/17/1356565.html C#与数据结构--树论--红黑树(RED BLACK TRE...
  • lc0817
  • lc0817
  • 2015年09月10日 17:04
  • 1715

红黑树的插入删除操作图解

相对于红黑树插入操作,删除操作复杂的多。 第一:先看最简单情况,即删除红色节点。删除红色节点,不影响红黑树平衡性质,如图:   只需要删除红色节点,不需要进行调整,因为不影响...
  • ningtaohaha123
  • ningtaohaha123
  • 2014年10月11日 11:18
  • 409

红黑树删除操作

红黑树删除操作: 红黑树要删除某个key值时,首先还是要查找该key值在树中的位置,查找方法和搜索二叉树方法相同. 要删除的结点分为两种情况: 1.有左右两个孩子都存在.两个孩子都存在时,在该节点的右...
  • Faded0104
  • Faded0104
  • 2017年07月13日 20:35
  • 161

红黑树(删除操作)

上一篇文章主要讲到了红黑树的基本性质以及插入节点的操作,有了上面的基础后,今天就把红黑树剩余的一个难点也就是删除节点的操作详细的讲一下。 红黑树节点的删除方法一开始的操作和二叉搜索树差不多,都是首先...
  • u011324138
  • u011324138
  • 2013年07月18日 13:03
  • 1316

红黑树的添加删除操作

来自: http://hi.baidu.com/coolinc/blog/item/3aa07f3e162502eb54e723b1.html介绍另一种平衡二叉树:红黑树(Red Black Tree...
  • Very_2
  • Very_2
  • 2010年07月09日 10:57
  • 17862

算法导论学习--红黑树详解之删除(含完整红黑树代码)

前面我们讨论了红黑树的插入的实现,基本思想是分类讨论;然后分情况讨论以后我们发现插入操作调整函数只需要处理三种情况,并不是太复杂。但是删除操作会更复杂一点,因为二叉搜索树的删除操作本身就分成了多种情况...
  • acm_lkl
  • acm_lkl
  • 2015年07月06日 20:05
  • 2330
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:红黑树(3) - 删除操作
举报原因:
原因补充:

(最多只允许输入30个字)