红黑树,看不懂你找我

一:什么是红黑树

红黑树是AVL树的一种流行变种,是具有以下五个特点的二叉查找树

  1. 每一个节点或者着成红色,或者着成黑色
  2. 根是黑色
  3. 每个叶节点Nil是黑色
  4. 如果一个节点是红色的,那么它的子节点必须是黑色的
  5. 每一条从某节点到某Nil指针的路径必须包含相同数目的黑色节点

二:关于红黑树的一般操作

对红黑树操作,最困难的就是保持上述的红黑树性质中的红色标记部分。

1.查找操作

红黑树是二叉查找树,所以其查找操作与一般的二叉查找树相同

  • 令根节点为当前节点
  • 当前节点为Nil,返回Nil
  • 要找的值等于当前节点,返回当前节点
  • 要找的值大于当前节点, 令右儿子为当前节点,重复步骤2
  • 要找的值小于当前节点,令左儿子为当前节点,重复步骤2

操作的时间复杂度O(logN)

2. 插入操作

当我们想向树中插入一个新节点时,通常把这个节点作为叶节点插入。

Part1:
假设把这个点涂成黑色,那完了,肯定违反了条件5,因为本来任意的节点到某Nil指针的路径中黑色节点数是相同的,现在加上黑色节点的这条路径黑色节点数度肯定会+1,于是原来的条件被破坏了,因此,新加的节点必须被涂成红色

Part2:
如果新插入的节点的父节点是黑色的,那么直接插入新的红节点就完事了

Part3:
如果新插入的节点的父节点是红色,那么条件4就被破坏了,这种情况下,我们必须在保持条件5不被破坏的同时,利用改变节点颜色以及树的旋转来满足所有条件。

2.1 新节点:我是红色的,我爹是红色的,我叔叔是黑色的

在这里插入图片描述

  • 设置P为黑色
  • 设置G为红色
  • 进行右单旋转

在这里插入图片描述

  • 设置X为黑色
  • 设置G为红色
  • 进行右双旋转

还有对称的两种情况,操作也是对称的

2.2 新节点:我是红色的,我爹是红色的,我叔叔也是红色的

在这里插入图片描述

  • 把G节点设置为红色
  • 把P节点设置为黑色
  • 把S节点设置为黑色
    在这里插入图片描述
  • 把G节点设置为红色
  • 把P节点设置为黑色
  • 把S节点设置为黑色

这时候,如果G的父节点也是红的,那么G的颜色翻转的操作就会影响性质4,于是我们对G节点以及其父节点GP和父节点的兄弟节点GPS进行2.1所示的旋转操作

注意如果G的父节点GP为红色,G父节点的兄弟节点GPS肯定不能为红色,只能为黑色,因为在红黑树中,不可能出现出现深度小于树的总深度且双兄弟都为红的情况,这种情况在其他的插入或删除过程中已经消除了。
在这里插入图片描述

GP刚好为根结点时,那么根据性质2,我们必须把GP重新设为黑色,那么树的红黑结构变为:黑黑红。换句话说,从根结点到叶子结点的路径中,黑色结点增加了。这也是唯一一种会增加红黑树黑色结点层数的插入情景。

还有对称的两种情况,操作也是对称的

难点来了,难点来了!!


其实不难

3.删除操作

删除操作一直一来是树这种ADT的难点所在

一般二叉搜索树的删除操作:

  • 该节点为叶节点的情况:可以直接删除,将其父节点的儿子指针设为Nil
  • 该节点只有一个非空子节点:可以直接删除,将其父节点的儿子指针指向其唯一儿子
  • 该节点有两个非空子节点:用该节点左子树的最大节点或者右子树的最小节点替换该节点,然后删除对应的左子树最大节点或者右子树最小节点,最终可以回到前两种情况。

好,到这里你肯定还是明白的对吧

现在考虑红黑树的删除操作。

注意:
根据一般二叉搜索树的删除操作来看,我们要删除的节点其实不一定是最终从图中移出去的节点,称最终从图中移出去的节点为替代点,我们先从右子树的最小节点(或左子树的最大节点)找到我们的替代点,与删除点的值交换,但是颜色都不变,然后再删除替代点,然后对树的性质进行恢复。而现在这些替代点都是一些树的末节点(区别于叶节点,我们现在将Nil节点视为黑色叶节点),删除操作便会简化许多,并可以归纳为像插入那样的几个类别。当然了替代点和我们要删除的点也有可能是同一点,但处理方法是一样的。

我们虽然删除了替代点,但是我们对树进行恢复时,还是会将该替代点放在树中参与恢复,恢复完成后再移掉。

在本文中,示例都默认是选择右子树的最小节点作为真正删除点,也可以选择左子树的最大节点

在这里插入图片描述

3.1替代点是红色的

直接从树中去掉即可,不会影响红黑树的性质,算法直接结束

不会出现替代点为红色且有儿子为非叶子节点的情况,所以这种情况是最简单的
在这里插入图片描述

3.2替代点是黑色的

替代点是黑色,那么删除之后树的性质就被破坏了,需要进行修复

3.2.1 有一个儿子为且必须为红色时

当替代节点只有一个儿子且为红色时
直接用它的红色儿子节点取代它,并将颜色改为黑色,这样所有经过替代节点的路径都将经过他的儿子,黑色高度不变。

在这里插入图片描述
注意这跟上面图不一样,这张图D节点是替代节点

不可能存在只有一个儿子且儿子为黑色的情况,那样本身就是不平衡的

3.2.2 有两个黑色儿子

当替代点是黑色的且有两个黑色儿子(可以为叶节点Nil)时,那他肯定有兄弟,那么又可以分为其他几类

  • 替代点是黑色,其兄弟节点是红色
  • 替代点是黑色,其兄弟节点是黑色
3.2.2.1 替代点的兄弟节点是红色

在这里插入图片描述

  • 将G节点也就是替代点的父节点设置为红色,
  • 兄弟节点S设置为黑色
  • 然后进行向左单旋转,

现在可以直接删掉D了吗?(以下都默认标识D为替代点) t a n 90 ° \hspace4ex 不行,tan90\degree

这个操作不改变任何路径的黑色高度,这时候删去D肯定会变的不平衡,我们只是把情况变为了兄弟节点为黑色的情况,也就是下面将要叙述的情况,我们接下来需要重新进入算法,进一步处理

3.2.2.2 替代点的兄弟节点是黑色

替代点D与其兄弟节点S都是黑色的,所以D的父节点颜色是不确定的,用绿色表示

又分为以下几种情况

3.2.2.2.1 当兄弟节点的两个儿子也都是黑色

在这里插入图片描述
PS:C1、C2可为Nil

  • S节点颜色变为红
  • G节点颜色变黑
  • 把P作为新的替代点

假设G一开始是黑色的,这个操作过后,所有一开始经过S节点的路径黑色高度-1,那么在删除D后,所有经过D节点的路径黑色高度也会-1,结局竟该死的甜美,但是经过G的比不经过G的黑色高度减一了,所以再在G上重新平衡处理

假设G一开始是红色的,这个操作后,所有一开始经过S节点的路径黑色高度不变,经过D的路径黑色高度+1,那么在删除D后,所有经过D节点的路径黑色高度又变回来了,结局竟还是该死的甜美,经过G为根的子树已经平衡了,再在G上重新平衡处理

注意当G是树的根时,就表示我们已经做完了,我们从所有路径去除了一个黑色节点,所有性质在上溯过程中都保持着。

3.2.2.2.2 当兄弟节点的左儿子是红色的,右儿子是黑色

在这里插入图片描述

  • C1设置为黑色
  • S设置为红色
  • 对S进行向右单旋转

这样的操作不改变任何路径的黑色高度,本来的平衡状态不变,所以删除D之后就破坏了原先的条件,还要进行自平衡变换,此时成了下面一种情况继续处理

3.2.2.2.3 当兄弟节点的右儿子是红色的,左儿子随意

在这里插入图片描述

  • 交换G和S的颜色
  • 设置兄弟节点的右儿子C2为黑色
  • 进行向左单旋转

该操作使所有变化前经过S节点的路径黑色高度都不变,经过D的路径黑色高度+1,在删除D后,所有经过G节点的路径都不变,达到平衡

说白了删除就是不断递归变换直到满足替代点的删除条件。

例子:删除30根节点
在这里插入图片描述

在这里插入图片描述
练习一下吧,这里有个在线红黑树工具,戳

三:渐进边界的证明

包含n个内部节点的红黑树的高度是 O ( l o g n ) O(logn)

定义:

h ( v ) v {\displaystyle h(v)}表示以节点{\displaystyle v}为根的子树的高度。
b h ( v ) v {\displaystyle bh(v)}表示从{\displaystyle v}到子树中任何叶子的黑色节点的数目
v (如果{\displaystyle v}是黑色则不计数它,也叫做黑色高度)。

v 2 b h ( v ) 1 引理:以节点{\displaystyle v}为根的子树有至少2^{bh(v)}-1个内部节点。
引理的证明(通过归纳高度):

归纳假设:
v N I L b h ( v ) = 0 b h ( v ) = 0 2 b h ( v ) 1 = 2 0 1 = 0 如果v的高度是零则它必定是NIL,因此{\displaystyle bh(v)=0}{\displaystyle bh(v)=0}。所以:2^{{bh(v)}}-1=2^{{0}}-1=0

h ( v ) = k 2 b h ( v ) 1 如果h(v)=k,有2^{bh(v)}-1个内部节点成立
h ( v ) = k + 1 于是h(v')=k+1
v h ( v ) > 0 b h ( v ) b h ( v ) 1 v 2 b h ( v ) 1 1 v 因为v'有h(v')>0 \\所以它是个内部节点。同样的它有的两个儿子,其黑色高度要么是bh(v')要么是bh(v')-1(依据v'是红色还是黑色)。通过归纳假设每个儿子都有至少2^{{bh(v')-1}}-1个内部接点,所以v'有:
2 b h ( v ) 1 1 + 2 b h ( v ) 1 1 + 1 = 2 b h ( v ) 1 2^{bh(v')-1}-1+2^{bh(v')-1}-1+1=2^{bh(v')}-1个内部节点。

使 ( 4 ) h ( r o o t ) 2 使用这个引理我们现在可以展示出树的高度是对数性的。\\ 因为在从根到叶子的任何路径上至少有一半的节点是黑色(根据红黑树性质4),\\根的黑色高度至少是 {\frac {h(root)}{2}}通过引理我们得到:

n 2 h ( r o o t ) 2 1    log ( n + 1 ) h ( r o o t ) 2    h ( r o o t ) 2 log ( n + 1 ) n 2 h ( r o o t ) 2 1    log ( n + 1 ) h ( r o o t ) 2    h ( r o o t ) 2 log ( n + 1 ) {\displaystyle n\geqslant 2^{\frac {h(root)}{2}}-1\leftrightarrow \;\log {(n+1)}\geqslant {\frac {h(root)}{2}}\leftrightarrow \;h(root)\leqslant 2\log {(n+1)}}n\geqslant 2^{{{\frac {h(root)}{2}}}}-1\leftrightarrow \;\log {(n+1)}\geqslant {\frac {h(root)}{2}}\leftrightarrow \;h(root)\leqslant 2\log {(n+1)}

O ( log n ) 因此根的高度是{\displaystyle {\text{O}}(\log n)}

在这里插入图片描述

发布了45 篇原创文章 · 获赞 31 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/include_IT_dog/article/details/105096737