谈谈红黑树

268 阅读10分钟

红黑树(Red Black Tree)

  • 红黑树也是一种自平衡的二叉搜索树
  • 也可称为平衡二叉B树 红黑树必须满足以下五条性质:
  1. 节点是Red或者Black
  2. 根节点是Black
  3. 叶子节点(外部节点、空节点)都是Black
  4. Red节点的子节点都是Black
  • Red节点的Parent都是Black
  • 从根节点到叶子节点的所有路径上不可能有2个连续的Red节点
  1. 从任意节点到叶子节点的所有路径都包含相同数目的Black节点

截屏2021-11-13 上午12.11.25.png

红黑树的等价变换

image.png

image.png

image.png

  • 红黑树4阶B树具有等价性(2-3树3阶B树不能完美匹配红黑树的所有情况)
  • Black节点和它的Red子节点融合在一起,形成一个B树节点
  • 红黑树Black节点个数和4阶B树的节点总个数相等

红黑树对比4阶B树

image.png

添加

  • 4阶B树所有节点的元素个数都满足[1,3]
  • B树中,新添加的元素一定是添加到叶子节点中
  • 建议新添加的节点默认为Red,这样能快速满足红黑树的性质(满足1、2、3、5,第4条不一定)
  • 如果添加的是根节点,染成Black即可

例如在下图中的红黑树中添加元素

image.png

由于添加元素都发生在叶子节点中,并且红黑树4阶B树具有等价性,那么上图便可以涵盖所有的添加情况,分别为节点17的左右子树、节点33的左右子树、节点46的左子树、节点50的左右子树、节点72的左右子树、节点76的右子树、节点88的左右子树,共计12种添加情况。

12种情况中可以看出如果是添加节点的父节点Black的话,因为添加元素是Red,添加后并不影响红黑树的特性,这时并不需要进行调整,但是如果父节点Red那么就会出现双红的局面,添加过后一定要进行调整,那么这里先可以将12种情况分为两大类添加后依然满足红黑树特性添加后不满足红黑树特性

添加后依然满足红黑树特性

有四种情况满足红黑树特性:parentBlack

image.png

添加后不满足红黑树特性

有八种情况不满足红黑树的性质4:ParentRed(双红)

image.png

同时这八种情况中又可以分为添加后不上溢上溢的情况,先来讨论不上溢的情况,不上溢有四种情况,同时又可以把不上溢的四种情况根据类比AVL树中的情况分为LLRRLRRL

不上溢

LL\RR

image.png

同样可以类比AVL树中的情况,可以看出这里是LLRR的情况。

判定条件:叔父节点不是Red

处理:

  1. parent染成Black,grand染成Red
  2. grand进行单旋操作(LL右旋转,RR左旋转)

操作后如图所示

image.png

LR\RL

image.png

同样判定条件是:叔父节点不是Red

处理:

1.自己染成Black,grand染成Red 2.如果是LRparent左旋转,grand右旋转 3.如果是RLparent右旋转,grand左旋转

处理之后如下图所示 image.png

上溢

image.png 上溢的情况共有四种,同样可以区分为LLLRRLRR,并且如图所示,这四种方式的处理是同样的方式来处理。

判定条件:叔父节点Red

处理:

1.parentuncle染成Black 2.grand染成Red向上合并(当做是新添加的节点) 3.grand向上合并时可能会再次发生上溢,若上溢持续到根节点,只需将根节点染成Black

接下来就按照LLLRRLRR四种不同的情况来分别看看添加后的情况

上溢-LL

image.png

image.png

上溢-RR

image.png

image.png

上溢-LR

image.png

image.png

上溢-RL

image.png

image.png

以上就是添加的12种情况也是所有情况的总结,下面用代码来实现

添加的代码实现

image.png

image.png

删除

删除的情况会比添加复杂一些,首先再来明确一下红黑树等价于4阶B树,而且真正被删除的元素一定是在叶子节点中,而且等价于4阶B树,那么删除的节点一定是以下情况中的一种

image.png 大体来看先分为:删除红色节点和删除黑色节点两个大情况来讨论

删除红色节点

image.png 由图可知,删除红色节点后依然保持红黑树所有特征,因此不用任何调整,所以直接删除即可

删除黑色节点

image.png

由图可以分为三种情况:

  • 有2个红色子节点的黑节点,这种情况可以不予考虑,因为它不可能直接被删除,而是找它的子节点删除
  • 有1个红色子节点的黑节点,红色节点可能在左边可能在右边
  • 黑色叶子节点

接下来对于这三种情况进行讨论

删除有一个红色子节点的黑色节点

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

处理: 把替代的红色子节点染成黑色就可以保持红黑树的性质

image.png

image.png

删除黑色叶子节点

在删除黑色叶子节点这种情况中,情况又会根据删除的黑色叶子节点的兄弟节点是红色还是黑色来划分,因为从B树的角度来看,删除叶子节点时会发生下溢,同时下溢会根据兄弟节点能不能借来分开讨论,但是红黑树这里又和B树的删除情况还不太一样,就是因为兄弟节点是否同在最后一层,这种情况便可以根据兄弟节点的颜色来进行判定,接下来会详细描述。

删除黑色叶子节点-兄弟节点是黑色
删除黑色叶子节点-兄弟节点是黑色-有至少一个红色子节点

这里先讨论兄弟节点可以出借的情况,一共分为下面三种 image.png

现在从左至右分别来说明处理过程:

  1. 删除88的黑色子节点会导致下溢,同时从兄弟节点76中可以出借节点88,这里首先要对76节点进行左左旋转,78节点上去之后情况便转化为第二种情况一样了,同为LL的情况。

  2. 删除88的黑色子节点会导致下溢,同时从兄弟节点76中可以出借节点72,这里情况比较简单,直接对80节点右旋转后,76成为子树的根节点,7280成为子节点,但是此时需要对76继承80原来的颜色,7280要染成黑色。

  3. 这种情况跟第二种分析的一样,唯一不同的是在80进行右旋转后,76原来的右节点78会成为80的左节点,并且颜色不变,依然为红色。

这里附上第一种情况转换一次的中间过程(此处暂未对颜色进行处理,故这时并不是红黑树的状态)

image.png

下图就是处理后的情况 image.png

总结:

这种情况的判定条件是:兄弟节点至少有一个红色子节点

处理过程:

  • 进行相应的旋转操作
  • 旋转后的中心节点要继承原来子树根节点的颜色
  • 旋转后左右子节点染为黑色
删除黑色叶子节点-兄弟节点是黑色-没有红色子节点

在删除黑色叶子节点、兄弟节点是黑色并且没有红色子节点这种情况的时候,还会根据被删除黑色子节点的父节点颜色为红色还是黑色来进行划分

分类讨论:

  • Parent是红色节点
  • Parent是黑色节点

先来讨论Parent是红色节点的情况,如图

image.png

删除88节点后产生下溢,节点80会和76组成一个新的节点,80颜色变黑,76变黑,结果为下图

image.png

总结:

判定条件:兄弟节点没有红色子节点,并且被删除的黑色子节点父节点红色

处理:

  • 兄弟节点染红,父节点染黑,即可修复红黑树性质

Parent是红色节点的情况已经讨论完成,现在来看Parent是黑色节点的情况

image.png

  • 兄弟节点没有红色子节点,并且被删除的黑色子节点的父节点是黑色
  • 会导致parent也发生下溢
  • 这时只需要把parent也当做是被删除的节点来处理即可
删除黑色叶子节点-兄弟节点是红色

image.png 在这种情况下要删除88,因为此时它的兄弟节点是55,但是根据B树的角度来看兄弟节点并不和它在一层,这时是没有办法借的,现在就是要想办法把88的兄弟节点弄到一层里,此时对80节点进行右旋转即可变为下图 image.png 这时的情况再次变为了刚讨论的兄弟节点是黑色的那种

总结:

判定条件:如果兄弟节点红色

处理方法:

  • 兄弟节点染成黑色父节点染成红色
  • 父节点进行右旋转

删除代码实现

Snip20211224_3.png

image.png

红黑树 VS AVL树 总结

再来回顾一下红黑树的五条性质:

  1. 节点是Red或者Black
  2. 根节点是Black
  3. 叶子节点(外部节点、空节点)都是Black
  4. Red节点的子节点都是Black
  • Red节点的Parent都是Black
  • 从根节点到叶子节点的所有路径上不可能有2个连续的Red节点
  1. 从任意节点到叶子节点的所有路径都包含相同数目的Black节点

只要满足这5条性质就可以保证红黑树等价于4阶B树

image.png

对于红黑树来说:

  • 相比于AVL树,红黑树的平衡标准比较宽松:没有一条路径会大于其他路径的2倍
  • 红黑树的平衡是一种弱平衡
  • 红黑树的最大高度是2log2(n+1)2*log_2(n+1),这依然是O(logn)的级别

AVL树总结:

  • 平衡标准比较严格:每个左右子树的高度差不超过1
  • 最大高度为1.44log2(n+2)1.3281.44 * log_2(n+2) - 1.328(100W个节点,AVL树最大树高28)
  • AVL树的平均时间复杂度:
    • 搜索:O(logn)
    • 添加:O(logn)以及O(1)次的旋转
    • 删除:O(logn)最多需要O(logn)次的旋转
  • 搜索、添加、删除都是 O(logn) 复杂度,其中添加仅需 O(1) 次旋转调整、删除最多需要 O(logn) 次旋转调整

红黑树总结:

  • 平衡标准比较宽松:没有一条路径会大于其他路径的2倍
  • 最大高度为2log2(n+1)2*log_2(n+1)(100W个节点,红黑树最大树高40)
  • 红黑树的平均时间复杂度:
    • 搜索:O(logn)
    • 添加:O(logn)以及O(1)次的旋转
    • 删除:O(logn)以及O(1)次的旋转
  • 搜索、添加、删除都是 O(logn) 复杂度,其中添加、删除都仅需 O(1) 次旋转调整

选择使用AVL树还是红黑树的参考:

  • 搜索的次数远远大于插入和删除,选择AVL树;搜索、插入、删除次数几乎差不多,选择红黑树
  • 相对于AVL树来说,红黑树牺牲了部分平衡性以换取插入/删除操作时少量的旋转操作,整体来说性能要优于AVL树
  • 红黑树的平均统计性能优于AVL树,实际应用中更多选择使用红黑树