红黑树、平衡二叉查找树

红黑树、平衡二叉查找树

平衡二叉查找树

非常常用的查找结构,各操作的时间复杂度与树的高度成正比

  • 插入
  • 删除
  • 查找

特点

  • 任意节点的左右子树高度相差不大于1
  • 左右子树都是平衡二叉树

最先发明的是AVL树,它严格符合平衡二叉查找树的定义,任意节点左右子树高度相差不超过1(高度平衡二叉查找树)

在这里插入图片描述

在这里插入图片描述

时间复杂度

假如树中有n个节点 树的高度是h,在理想情况下h近似为log n , 所以各项操作的时间复杂度是大O-logn

在这里插入图片描述

红黑树

建议:在学红黑树之前需要掌握好这些内容跳转

扫描二维码关注公众号,回复: 14611132 查看本文章

这里在介绍之前是默认你是知道4阶B树的。好了,正题开始!

先给大家看一下一般的红黑树的样子

在这里插入图片描述

是不是看上去一脸懵呢?如果是的话那就对了。为了让你能够看得懂一些,我再告诉你一些它的一些性质:

  • 红黑树是实际应用中最常用的平衡二叉查找树

特点

首先,红黑树是一个二叉搜索树,它在每个节点增加了一个存储位记录节点的颜色,可以是RED,也可以是BLACK;通过任意一条从根到叶子简单路径上颜色的约束,红黑树保证最长路径不超过最短路径的二倍,因而近似平衡(最短路径就是全黑节点,最长路径就是一个红节点一个黑节点,当从根节点到叶子节点的路径上黑色节点相同时,最长路径刚好是最短路径的两倍)。它同时满足以下特性:

  • 节点是红色黑色

  • 根是黑色

  • 叶子节点(外部节点,空节点)都是**黑色,**这里的叶子节点指的是最底层的空节点(外部节点),下图中的那些null节点才是叶子节点,null节点的父节点在红黑树里不将其看作叶子节点

  • 红色节点的子节点都是黑色

    • 红色节点的父节点都是黑色
    • 从根节点到叶子节点的所有路径上不能有 2 个连续的红色节点
  • 从任一节点到叶子节点的所有路径都包含相同数目的黑色节点

  • 红黑树适合作为查找和存储的数据结构

在这里插入图片描述

红黑树效率

  • 红黑树的查找,插入和删除操作,时间复杂度都是O(logN)。

  • 查找操作时,它和普通的相对平衡的二叉搜索树的效率相同,都是通过相同的方式来查找的,没有用到红黑树特有的特性。

  • 但如果插入的时候是有序数据,那么红黑树的查询效率就比二叉搜索树要高了,因为此时二叉搜索树不是平衡树,它的时间复杂度O(N)。

  • 插入和删除操作时,由于红黑树的每次操作平均要旋转一次和变换颜色,所以它比普通的二叉搜索树效率要低一点,不过时间复杂度仍然是O(logN)。总之,红黑树的优点就是对有序数据的查询操作不会慢到O(logN)的时间复杂度。

红黑树和AVL树的比较

  1. AVL树的时间复杂度虽然优于红黑树,但是对于现在的计算机,cpu太快,可以忽略性能差异
  2. 红黑树的插入删除比AVL树更便于控制操作
  3. 红黑树整体性能略优于AVL树(红黑树旋转情况少于AVL树)

红黑树的等价变换

在这里插入图片描述

上面这颗红黑树,我们来将所有的红色节点上移到和他们的父节点同一高度上,就会形成如下结构

在这里插入图片描述

这个结构很明显,就是一棵四阶B树(一个节点最多放三个数据),如果画成如下的样子大家应该就能看的更清晰了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GyaBkltE-1652961298411)(image-20220519111102641.png)]

由上面的等价变换我们就可以得到如下结论:

  1. 红黑树 和 4阶B树(2-3-4树)具有等价性
  2. 黑色节点与它的红色子节点融合在一起,形成1个B树节点
  3. 红黑树的黑色节点个数 与 4阶B树的节点总个数相等
  4. 在所有的B树节点中,永远是黑色节点是父节点,红色节点是子节点。黑色节点在中间,红色节点在两边。

可以利用四阶B树与红黑树等价的性质,以红黑树转换成B树之后的节点情况来进行一个分类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NJ8euSYu-1652961298412)(image-20220519111217226.png)]

红黑树的操作

红黑树的基本操作和其他树形结构一样,一般都包括查找、插入、删除等操作。前面说到,红黑树是一种自平衡的二叉查找树,既然是二叉查找树的一种,那么查找过程和二叉查找树一样,比较简单,这里不再赘述。相对于查找操作,红黑树的插入和删除操作就要复杂的多。尤其是删除操作,要处理的情况比较多,下面就来分情况讲解。

旋转操作

在分析插入和删除操作前,先说明一下旋转操作,这个操作在后续操作中都会用得到。旋转操作分为左旋和右旋,左旋是将某个节点旋转为其右孩子的左孩子,而右旋是节点旋转为其左孩子的右孩子。这话听起来有点绕,所以还是请看下图:

图例

上图包含了左旋和右旋的示意图

左旋

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZkVUtTUo-1652961298412)(image-20220519100625612.png)]

右旋

在这里插入图片描述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4XGbU5di-1652961298413)(image-20220519143628960.png)]

旋转操作本身并不复杂,上面分析了右旋操作,左旋操作与此类似,只是右旋转的逆操作。

插入操作

红黑树的插入过程和二叉查找树插入过程基本类似,不同的地方在于,红黑树插入新节点后,需要进行调整,以满足红黑树的性质。

性质1规定红黑树节点的颜色要么是红色要么是黑色,那么在插入新节点时,这个节点应该是红色还是黑色呢?答案是红色,原因也不难理解。如果插入的节点是黑色,那么这个节点所在路径比其他路径多出一个黑色节点,这个调整起来会比较麻烦(参考红黑树的删除操作,就知道为啥多一个或少一个黑色节点时,调整起来这么麻烦了)。如果插入的节点是红色,此时所有路径上的黑色节点数量不变,仅可能会出现两个连续的红色节点的情况。这种情况下,通过变色和旋转进行调整即可,比之前的简单多了。所以插入的时候将节点设置为红色,可以保证满足性质 1、2、3、5 ,只有性质4不一定满足,需要进行相关调整。如果是添加根节点,则将节点设定为黑色。

插入操作的所有情况

我们在分析红黑树各种插入情况的时候,将其等价转换为B树,这样我们能够更直观的进行分类,首先确定几条性质:

  • B树中,新元素必定是添加到叶子节点中(最底层的节点)
  • 4阶B树所有节点的元素个数 x 都符合 1 ≤ x ≤ 3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ytfKO5QD-1652961298413)(image-20220519144627315.png)]

在上一章节红黑树的等价变换中,我们讲到了红黑树转换成B树总共有四种情况,也就是上图中叶子节点这四种情况,那么在我们进行插入操作的时候,会将节点插入到所有的叶子节点中,总共就会有12种情况,其中四种情况满足红黑树的性质,8种情况不满足红黑树性质。

满足红黑树性质4

有 4 种情况满足红黑树的性质 4 :parent 为黑色节点。这四种情况不需要做任何额外的处理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Um14Q7aY-1652961298413)(image-20220519145046095.png)]

不满足红黑树性质4

有 8 种情况不满足红黑树的性质 4 :parent 为红色节点( Double Red ),其中左面4种属于B树节点上溢的情况(一个4阶B树节点中最多存放三个数,这四种情况本来已经有3个了,又插入了1个,变成了4个,超出了4阶B树节点的容量范围,这种情况称为上溢)。这八种情况需要进行额外的处理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2gJhqhDz-1652961298414)(image-20220519145108007.png)]

LL和RR插入情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RFBtTpFa-1652961298414)(image-20220519145142950.png)]

如上图,插入52和60的位置分别是RR情况和LL情况。

RR情况:父节点为祖父节点的右节点,插入节点为父节点的右节点

LL情况:父节点为祖父节点的左节点,插入节点为父节点的左节点

这两种情况很明显,插入节点为红色,父节点也为红色,父节点的子节点为红色显然违背了红黑树的性质四,我们需要对这种情况进行修复,使其重新满足红黑树性质。

**判定条件:**uncle 不是红色节点。

这里的两种情况,他们的插入节点都是没有叔父节点的,所以叔父节点也不可能是红色。

案例修复

我们在红黑树等价转换那一章节也讲过了,红黑树等价转换成B树之后,B树节点的中间节点(父节点)都是黑色,两边的节点(子节点)都是红色。但是上面两种情况插入后,插入位置的B树节点并不满足这个条件,所以我们对其进行修复,使其满足B树节点的条件之后,也就重新恢复了红黑树性质。

B树节点中的中间节点大小介于两个子节点之间。以上图RR情况为例,插入节点52的原父节点应该放在B树节点中间的位置,应当将其染成黑色。插入节点52的原祖父节点46,应当将其转换为插入节点原父节点的子节点,所以将其染成红色。LL情况同理

完成染色之后,需要对原祖父节点进行单旋操作,来进行父节点,子节点的重新分配。以上图为例:

  • RR情况应该原祖父节点46左旋,将插入节点的原父节点50旋转到中间的位置。
  • LL情况应当原祖父节点76右旋,将插入节点的原父节点72旋转到中间的位置。

修复之后的结果如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oY9U7P9E-1652961298414)(image-20220519150225766.png)]

修复步骤总结

  1. parent 染成黑色,grand 染成红色
  2. grand 进行单旋操作
    1. LL:右旋转
    2. RR:左旋转
LR和RL插入情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tin5HtWW-1652961298414)(image-20220519150510712.png)]

如上图,插入48和74的位置分别是RL情况和LR情况。

RL情况:父节点为祖父节点的右节点,插入节点为父节点的左节点

LR情况:父节点为祖父节点的左节点,插入节点为父节点的右节点

这两种情况和上面的两种情况一样,插入节点为红色,父节点也为红色,父节点的子节点为红色显然违背了红黑树的性质四,我们需要对这种情况进行修复,使其重新满足红黑树性质。

判定条件:uncle 不是红色节点。

这两种情况的插入节点也是没有叔父节点的。

案例修复

B树节点中的中间节点大小介于两个子节点之间。以上图RL情况为例,插入节点48大小介于原父节点和原祖父节点之间,它应该是B树节点中的中间节点,所以将插入节点48染成黑色,将原祖父节点46染成红色来作为插入节点的子节点。LR情况同理

完成染色之后,需要进行双旋操作,来进行父节点,子节点的重新分配。以上图为例:

  • RL情况应该原父节点50右旋,将插入节点48上移到原父节点50的高度,然后将插入节点的原祖父节点46进行左旋,将插入节点48移动到中间位置,成为中间节点。
  • LR情况应该原父节点72左旋,将插入节点74上移到原父节点72的高度,然后将插入节点的原祖父节点76进行右旋,将插入节点74移动到中间位置,成为中间节点。

修复之后的结果如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nh7jhChI-1652961298415)(image-20220519151437368.png)]

修复步骤总结:

  1. 插入节点染成黑色,grand 染成红色
  2. 进行双旋操作
    • LR:parent 左旋转, grandFather 右旋转
    • RL:parent 右旋转, grandFather 左旋转
上溢的LL插入情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nXoLHRbs-1652961298415)(image-20220519154700344.png)]

如上图,插入10的位置是上溢的LL情况。

上溢LL情况:父节点为祖父节点的左节点,插入节点为父节点的左节点。并且构成的新的B树节点已经超过了B树节点容量大小范围。

这种情况和之前非上溢的四种情况一样,插入节点为红色,父节点也为红色,父节点的子节点为红色显然违背了红黑树的性质四,我们需要对这种情况进行修复,使其重新满足红黑树性质。

判定条件:uncle 是红色节点。满足这个条件的就都是上溢的情况,上溢的修复只需要染色,不需要旋转。

案例修复

像这种上溢的情况,就需要从溢出的B树节点中选出一个节点进行向上合并,选择B树节点中中间的树去进行向上合并,这里中间的两个节点就是原父节点17和原祖父节点25,选这两个哪一个向上合并都是对的,但是我们最好选择以后方便操作的,很显然,应该选择原祖父节点25来进行向上合并,因为向上合并就是和最上层的38和55来组合成新的B树节点,向上合并的节点肯定是一个子节点,需要与上层相连,而原祖父节点25本身就已经和上层连接了,相对更加方便后续的操作。原祖父节点向上合并后,将其染成红色。

原祖父节点25向上合并后,它原来左右两边的节点需要分裂成两个子树,也就是原父节点17和插入节点10形成一个子树,原叔父节点33形成一个子树。这两个分裂形成的树都是以后25的子树。左边的子树由原父节点作为中间节点,染成黑色,右边的子树由原叔父节点作为中间节点,染成黑色。

修复之后的结果如下图:

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7U2Q7mA8-1652961298415)(image-20220519155045609.png)]

修复步骤总结:

  • parent、uncle 染成黑色
  • grand 向上合并
    • 将向上合并的grand染成红色,相对上一层,就当做是新添加的节点,再次来一遍插入情况的判断,进行处理。

grand 向上合并时,可能继续发生上溢。这种情况就继续递归调用修复方法就可以了。若上溢持续到根节点,只需将根节点染成黑色即可(这个意思就是说断向上上溢,一直上溢到了B树的根节点位置了,只需要将向上合并的节点变成黑色作为红黑树的根节点即可。因为从B树根节点选择出来上溢的节点,肯定就是作为整个红黑树的根节点了)。

上溢的RR插入情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aFhfdVmy-1652961298416)(image-20220519155214359.png)]

如上图,插入36的位置是上溢的RR情况。

上溢RR情况:父节点为祖父节点的右节点,插入节点为父节点的右节点。并且构成的新的B树节点已经超过了B树节点容量大小范围。

**判定条件:**uncle 是红色节点

案例修复

上溢RR情况的修复,和上溢LL情况基本一致,只是修复的位置不同,这里中间的两个节点就是原父节点33和原祖父节点25,选择原祖父节点25来进行向上合并,原祖父节点向上合并后,将其染成红色。

原祖父节点25向上合并后,它原来左右两边的节点需要分裂成两个子树,也就是原父节点33和插入节点36形成一个子树,原叔父节点17形成一个子树。这两个分裂形成的树都是以后25的子树。左边的子树由原叔父节点作为中间节点,染成黑色,右边的子树由原父节点作为中间节点,染成黑色。

修复之后的结果如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CgLrkC07-1652961298416)(image-20220519155410203.png)]

修复步骤总结:

  1. parent、uncle 染成黑色
  2. grand 向上合并
    • 染成红色(其实染成红色就已经是完成了向上合并,因为祖父节点和祖父节点的父节点的连接指向并没有变),当做是新添加的节点进行处理
上溢的LR插入情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sAEG1307-1652961298416)(image-20220519155621569.png)]

如上图,插入20的位置是上溢的LR情况。

上溢LR情况:父节点为祖父节点的左节点,插入节点为父节点的右节点。并且构成的新的B树节点已经超过了B树节点容量大小范围。

判定条件:uncle 是红色节点

案例修复:

上溢LR情况的修复,和其他上溢情况基本一致,只是修复的位置不同,这里中间的两个节点就是原父节点17和原祖父节点25,选择原祖父节点25来进行向上合并,原祖父节点向上合并后,将其染成红色。

原祖父节点25向上合并后,它原来左右两边的节点需要分裂成两个子树,也就是原父节点17和插入节点20形成一个子树,原叔父节点33形成一个子树。这两个分裂形成的树都是以后25的子树。左边的子树由原父节点作为中间节点,染成黑色,右边的子树由原叔父节点作为中间节点,染成黑色。

修复之后的结果如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v3BptxEa-1652961298416)(image-20220519155638416.png)]

修复步骤总结:

  1. parent、uncle 染成黑色
  2. grand 向上合并
    • 染成红色,当做是新添加的节点进行处理
上溢的RL插入情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N441bvfc-1652961298417)(image-20220519155819975.png)]

如上图,插入30的位置是上溢的RL情况。

上溢RL情况:父节点为祖父节点的右节点,插入节点为父节点的左节点。并且构成的新的B树节点已经超过了B树节点容量大小范围。

判定条件:uncle 是红色节点

案例修复

上溢RL情况的修复,和其他上溢情况基本一致,只是修复的位置不同,这里中间的两个节点就是原父节点33和原祖父节点25,选择原祖父节点25来进行向上合并,原祖父节点向上合并后,将其染成红色。

原祖父节点25向上合并后,它原来左右两边的节点需要分裂成两个子树,也就是原父节点33和插入节点30形成一个子树,原叔父节点17形成一个子树。这两个分裂形成的树都是以后25的子树。左边的子树由原叔父节点作为中间节点,染成黑色,右边的子树由原父节点作为中间节点,染成黑色。

修复之后的结果如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v23oW8BJ-1652961298417)(image-20220519155857724.png)]

修复步骤总结:

  1. parent、uncle 染成黑色
  2. grand 向上合并
    • 染成黑色,当做是新添加的节点进行处理
插入情况总结

插入一共有12种情况:

  • 插入节点的父节点是黑色的情况有4种这种情况仍然会维持红黑树的性质,则不需要进行额外处理。

  • 插入节点的父节点是红色的情况有8种这种情况不满足红黑树的性质4,需要进行额外的修复处理。

    • 这8种情况中:

      • 叔父节点不是红色的情况有4种 这些情况都是非上溢,需要通过重新染色和旋转来进行修复

      • 叔父节点是红色的情况有4种 这些情况都是上溢的,只需要通过祖父节点上溢合并和染色即可完成修复

删除操作

相较于插入操作,红黑树的删除操作则要更为复杂一些。B树中,最后真正被删除的元素都在叶子节点中。所以在红黑树中,被删除的节点一定也在最后一层。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yo0Bb6NY-1652961298417)(image-20220519160231271.png)]

删除操作的所有情况
删除红色节点

如果删除的节点是红色直接删除,不用作任何调整。因为删除最后一层的红色节点,并没有影响红黑树的任何性质。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cMLysQZH-1652961298417)(image-20220519160433934.png)]

删除黑色节点

有3种情况:

  1. 拥有 2 个红色子节点的黑色节点
    • 不可能被直接删除,因为会找它的子节点替代删除,因此不用考虑这种情况
  2. 拥有 1 个红色子节点的黑色节点
  3. 黑色叶子节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-luUXfJUQ-1652961298418)(image-20220519160527106.png)]

删除拥有1个红色子节点的黑色节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiJxgvnv-1652961298418)(image-20220519160622522.png)]

删除拥有1个红色子节点的黑色节点的情况,是需要我们做相关的处理的。这里删除的就是节点46和76,他们只有一个红色子节点。

对于一个二叉树来说,删除一个度为1的节点(度指的是一个节点的子节点个数),将其删除后需要用它唯一的子节点来进行替换。而红黑树的这种情况的判定条件,就是判定要替代删除节点的子节点是不是红色

判定条件:用以替代的子节点是红色节点

案例修复:

第一步:

将46与父节点的连接断开

第二步:

46唯一的红色子节点50作为代替46的节点,将其与46的父节点进行连接

第三步:

断开46与50的连接,将46删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aIt7DbrA-1652961298418)(image-20220519161041965.png)]

删除节点76的过程与删除节点46相同

第一步:

将76与父节点的连接断开

第二步:

76唯一的红色子节点72作为代替76的节点,将其与76的父节点进行连接

第三步:

断开76与80的连接,将46删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ySeVNVc-1652961298418)(image-20220519161223786.png)]

但是现在我们发现,80是红色节点,它的子节点72还是红色节点,这样明显不符合红黑树的性质,还需要进一步修复。

将替代的子节点染成黑色即可保持红黑树性质,修复完成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tl7xT30T-1652961298419)(image-20220519161236636.png)]

修复步骤总结:

  1. 用删除节点的唯一子节点对其进行替代
  2. 将替代节点染成黑色
删除黑色叶子节点——删除节点为根节点

一棵红黑树只有一个黑色根节点(也就是唯一的一个叶子节点,整个红黑树只有这一个黑色节点),可直接删除该节点,无需做其他操作。

删除黑色叶子节点——删除节点的兄弟节点为黑色

讲这种删除情况前先举一个例子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Lqc7Izl-1652961298419)(image-20220519161910649.png)]

上面这个我们要删除节点88,该节点为黑色叶子节点,它的兄弟节点是黑色76。从B树的角度来看,如果删除88,因为四阶B树的节点中最少存有1个元素,如果不足,则会造成下溢。也就是需要从88的兄弟节点中借一个子节点出来。这就是这一节我们讨论的删除情况的核心修复思想。
兄弟节点至少有1个红色子节点

下面三个图分别对应着兄弟节点至少有一个红色子节点的三种情况。删除节点为88,为黑色叶子节点,它的兄弟节点是76,为黑色。兄弟节点76都至少有一个红色子节点,三种情况分别为76拥有一个红色右子节点,76拥有一个红色左子节点,76拥有两个红色子节点。因为兄弟节点有红色子节点,所以可以借出一个节点来进行修复。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ms6RUKNS-1652961298419)(image-20220519161946485.png)]

这三种情况,黑色叶子节点被删除后,会导致B树节点下溢(比如删除88),就可以从兄弟节点中借出一个红色子节点来进行修复。

**判定条件:**兄弟节点至少有 1 个红色子节点

案例修复:

1、兄弟节点有一个右子节点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IeARxnS5-1652961298420)(image-20220519165622789.png)]

先将88节点删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u9kUYYPg-1652961298420)(image-20220519165644486.png)]

B树下性质

​ 下溢说明:B树

  • 对于一个n阶B树(n>=2):
  • 根节点元素个数的取值范围是[1 , n-1] ,即4阶B树根节点元素个数取值范围是[1 , 3]
  • 非根节点元素个数在[ ceiling(n/2)-1 , floor(n-1) ]范围内s(ceiling表示向上取整,floor表示向下取整),即4阶B树的非根节点元素个数的取值范围是[1 , 3]
  • 设每个节点的元素个数为 x 个,那么起子节点的个数则为x + 1个

删掉之后,从B树的角度来看就出现了下溢,这个时候就需要父节点下来,在兄弟节点的子结点中找一个,将他升上去代替。具体的实现就是要对节点进行旋转。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cw0js3dv-1652961298420)(image-20220519171513841.png)]

我们可以看出,80、76、78组成的树是一个LR的情况,先对76进行左旋转(可以将76看作父节点),这样78就上去了,再对80进行右旋转(可以将80看成祖父节点),80就下去了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z32T5xO0-1652961298420)(image-20220519171555864.png)]

旋转完了之后,如上图。将旋转完之后的中心节点(就是78、76、80组成的树的最中心的节点,这里就是78)进行重新染色,继承删除节点的父节点80的颜色。最后再将78、76、80组成的树的左右两个节点染成黑色即可完成修复。

2.兄弟节点有一个左子节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4SEaFjAK-1652961298421)(image-20220519171715755.png)]

先将88节点删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bbej3Eq3-1652961298421)(image-20220519171725694.png)]

删掉之后,从B树的角度来看就出现了下溢,这个时候就需要父节点下来,在兄弟节点的子结点中找一个,将他升上去代替。具体的实现就是要对节点进行旋转。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EedknuTl-1652961298421)(image-20220519171737701.png)]

我们可以看出,80、72、78组成的树是一个LL的情况,直接对80进行右旋(将80看成是祖父节点)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e5gZBvx4-1652961298421)(image-20220519172004611.png)]

旋转完了之后,如上图。将旋转完之后的中心节点(就是78、72、80组成的树的最中心的节点,这里就是76)进行重新染色,继承删除节点的父节点80的颜色。最后再将78、72、80组成的树的左右两个节点染成黑色即可完成修复。

3.兄弟节点有两个左右子节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EW8czl9w-1652961298422)(image-20220519172045755.png)]

先将88节点删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LhyLvxCn-1652961298422)(image-20220519172510836.png)]

删除之后,其实可以有两种旋转可以进行修复,既可以使用LL方式进行旋转,也可以使用LR方式进行旋转。但是因为LL方式只需要旋转一次,我们就选用LL方式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MX4qk0e3-1652961298422)(image-20220519172555316.png)]

直接对80进行右旋

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lxN8Oiwu-1652961298422)(image-20220519172609894.png)]

旋转完了之后,如上图。将旋转完之后的中心节点(就是78、72、76、80组成的树的最中心的节点,这里就是76)进行重新染色,继承删除节点的父节点80的颜色。最后再将78、72、76、80组成的树的左右两个节点染成黑色即可完成修复。

修复步骤总结:

  1. 进行旋转操作
  2. 旋转之后的中心节点继承父节点(删除节点的父节点)的颜色
  3. 旋转之后的左右节点染为黑色

4.兄弟节点没有红色子节点

当删除节点的兄弟节点没有红色节点可以借出的情况下,就需要父节点来向下合并进行修复,父节点向下和兄弟节点合并成新的B树节点来解决下溢。

**判定条件:**兄弟节点没有1个红色子节点

案例修复:

1、父节点为红色:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aJSmDLcp-1652961298423)(image-20220519172908228.png)]

删除节点88,出现下溢

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Giw71Rxj-1652961298423)(image-20220519172916249.png)]

因为兄弟节点76没有可以借出的红色节点,所以需要父节点80来向下与76合并进行修复

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I2eECG0e-1652961298423)(image-20220519172927197.png)]

将兄弟节点76染成红色,父节点80染成黑色即可完成修复

5.父节点为黑色

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GsDnPcq0-1652961298423)(image-20220519191445650.png)]

删除节点88,删除之后节点88就会出现下溢

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uEsH89Yp-1652961298424)(image-20220519191508377.png)]

删除之后父节点80应该向下合并进行修复,但是因为父节点80为黑色,如果向下合并之后,其实就相当于80这个节点也出现了下溢。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-emOppagG-1652961298424)(image-20220519191732319.png)]

这个时候只需要把父节点当作被删除的节点进行处理即可

修复步骤总结:

  1. 父节点向下与兄弟节点进行合并
  2. 将兄弟染成红色、父节点染成黑色即可修复红黑树性质
    • 如果父节点是黑色,直接将父节点当成被删除的节点处理,来修复父节点的下溢情况
删除黑色叶子节点——删除节点的兄弟节点为红色

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vUKWZqQ1-1652961298424)(image-20220519192309167.png)]

删除节点的兄弟节点为红色,这样删除节点出现下溢后没办法通过兄弟节点来进行修复。这就需要先把红黑树转换为兄弟节点为黑色的情况,就可以套用上面讲的修复方法来进行修复了。

**判定条件:**兄弟节点是红色

案例修复:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fklg5pn7-1652961298424)(image-20220519192350444.png)]

删除88节点之前,需要先转换成兄弟节点为黑色的情况,当前88的兄弟节点是红色55。可以将其看作LL情况,对父节点80进行右旋转,这样55就被移动上去了,成了80的父节点。76也被移动上去了,成了80的子节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mfsmGdFE-1652961298425)(image-20220519192531320.png)]

这种情况,删除节点88的兄弟节点就变成了黑色,并且没有红色子节点,可以继续套用之前讲的方法来进行修复了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nT8XbMHY-1652961298425)(image-20220519192702697.png)]

删除掉88,将80染成黑色,76染成红色,完成修复。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yro2Esv3-1652961298425)(image-20220518164615411-16528635775496.png)]

  • 特点

    • 根节点是黑色

    • 叶节点是不存储数据的黑色空节点

    • 任何相邻的两个节点不能同时为红色

    • 任意节点到其可达到的叶节点间包含相同数量的黑色节点

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43900956/article/details/124870254