数据结构 - 学习笔记 - 红黑树前传——234树

Posted 笑虾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构 - 学习笔记 - 红黑树前传——234树相关的知识,希望对你有一定的参考价值。

数据结构 - 学习笔记 - 红黑树前传——234树

简介

234树——234Trees
在学习红黑树前需要先了解234树。因为红黑树就是由234树演变出来的。(红黑树是234树的一种实现)
了解了234树才能明白红黑树颜色变化的底层逻辑。

  1. 明明是包含123个结点,为什么不叫123树而叫234树。我的理解是:因为树的特性就是分叉,结点的命名是按它的分叉能力来的。n结点就是能分n个叉的结点。(吐槽:真是跟制动有异曲同工之妙。)
  2. 234树 就是 4阶B树。也就是允许结点最多有4个子结点平衡多路查找树。
  3. 234树 是倒着长的。新元素插入到叶子,然后触发分裂向上提升元素成父级。

结点类型

结点结点内容子结点个数
子结点值域
对应红黑树结点
2结点1个元素。
如:a
2个子结点或子结点
( , a), (a, )
黑色a
3结点2个元素。
如:a,b
3个子结点或子结点
( , a) , (a, b) , (b, )
父结点必需是黑色且有2种情况
1. 黑色b—L→红色a
2. 黑色a—R→红色b
4结点3个元素。
如:a,b,c
4个子结点或子结点
( , a) , (a, b) , (b, c) , (c, )
红色a←L—黑色b—R→红色c

红黑树对应关系

  1. 上图中没有画出具体的子结点 仅用虚线框标识了一下子结点的取值范围。
  2. 不难看出,只要将红黑树中的红结点向上一提,与父结点合并,就反推出了234树
  3. 同时根据3结点的特性,可以看出234树红黑树一对多的关系。
  4. 在平时分析红黑树时,可以直接在脑海里映射成234树来分析。这样变化旋转操作就有据可依,而不是死记硬背了。

插入逻辑

插入场景插入前插入示例值插入后结论
当前无结点5[5]直接插入就完事了。
当前2结点[5]3[3, 5]2结点升级为3结点
当前3结点[3, 5]7[3, 5, 7]3结点升级为4结点
当前4结点[3, 5, 7]8[5]
[3, 7, 8]
4结点 插入新值时,会触发分裂
先中间值 5 上升,再与父结点合并。

插入步骤演示

下图演示了234树的插入步骤,以及触发分裂的效果。(新插入的元素,按红黑树路径标为红色)

下图对应234树插入步骤,在右侧列出对应的红黑树。因为3结点红黑树存在两种情况,所以按排列组合方式一一列出。
对照前文的与红黑树对应关系,可以看到黑红颜色背后的逻辑来源于234树

1. 插入2结点

2结点插入新值,直接升级为3结点,无需任何调整。

2. 插入3结点(红黑树旋转)

3结点插入新值,直接升级为4结点,无需任何调整。
但在3结点对应的红黑树中,可能出现不平衡的情况。需要旋转调整实现平衡。

2.1. 共对应6种红黑树情形

  1. 旋转方向的逻辑可以想象天平。左边重了往右挪(旋)右边重了往左挪(旋)
  2. 从上图可以看到有3个位置能插入子结点。对应 6 种红黑树的情形。
  3. 其中有2种是平衡的,无需调整。剩下4种 需要通过旋转实现平衡。

2.2. 有4种情形需要旋转

虽然共有4种 情形,但其中 LR可以转为LLRL可以转为RR。总之就是有拐弯的,都是转为一条直线,再处理。
1.1. LR 左旋1次,转为 LL
1.2. LL 右旋1次,实现平衡。
2.1. RL 右旋1次,转为 LL
2.2. RR 左旋1次,实现平衡。

3. 插入4结点(红黑树变色)

3.1. 234树→红黑树

先简单的把 4结点红黑树 对应关系,罗列出来。根据新结点插入的位置不同,对应的红黑树也有所差异:

对应上图的步骤序号。

  1. 原234树为 357.
  2. 插入新元素。将要触发分裂。
  3. 先分裂。然后按新值大小,找到插入位置,与原有的2结点 合并成为3结点
    3.1. 中值上提为父结点,如果原本有父结点,分裂出去的结点,与原父结点合并。
    3.2. 如果原来的父结点也是一个4结点,将递归触发分裂
    3.3. 剩下两个结点,小的为左,大的为右。
  4. 234树结点转红黑树结点。
    4.1. 所有 2结点 变为黑色。
    4.2. 3结点 展开,上黑下红。

3.2. 触发分裂

单独分析一下触发分裂效果。

  1. 演示了从234树的角度来染色的逻辑(左)。
  2. 演示了从红黑树的角度来染色的公式(右)。
  3. 如果当前操作的只是一颗子树。比如结点2也是红色(需要旋转,对应RR公式),则需要继续处理,直至根。

3.3.有4种情形需要变色实现平衡

  1. 【234树】 插入新元素。将要触发分裂。
  2. 【234树】 先分裂。然后找到待插入的目标位置,与原有的2结点 合并成为3结点
  3. 【红黑树】 这是一个中间状态,为了便于观察才把它画出来。(3结点展开,但未调色,暂时还保持着不平衡的状态,便于观察)
  4. 【红黑树】 结点、叔伯结点变成黑色祖父结点变成红色
    4.1. 结点与祖父结点调换颜色:满足红结点子必的定义。同时对于插入新结点的这一路径来说黑结点数未发生变化。
    4.2. 叔伯结点变成黑色祖父结点原本作为公共的黑结点,挪给左路后,右路就少了一个黑结点。因此 叔伯要站出来变维持平衡。
  5. 【红黑树】 最后祖父结点更新为当前结点。
    5.1. 判断曾祖是否为红色。如果是,则需要向上递归调整颜色,一直到根。
    5.2. 如果是根,直接染

3.4. 递归调整颜色

插入新结点 1 后递归触发变色。直到根结点为止。

删除逻辑

删除操作:根据删除目标所在位置不同,共有几种情况需要分别处理。

  • 删除目标为叶子结点
  1. 目标在4结点中,删除后变成3结点。
  2. 目标在3结点中,删除后变成3结点。
  3. 目标是2结点,有三种情况:
    3.1. 兄弟是3个结点4个结点
    3.2. 两个兄弟结点都是2结点,但父结点3结点4结点
    3.3. 兄弟结点父结点都是2结点
  • 如果删除目标非叶结点(有子结点)
  1. 找到目标前驱后继结点。前驱后继必定是叶结点。
  2. 目标值与前驱后继交换。交换后目标结点便是叶结点了。
  3. 叶结点删除规则处理。

1. 删除4结点

删除一个元素,变成3结点。保持平衡。
4结点 的删除,如果忽略掉它的兄弟结点。本质上还是一个3结点的删除。
对应红黑树:

  • 红结点:直接删除即可。
  • 黑结点:删除黑结点,红结点补位,并变成黑色。

  1. 234树结点,蓝色 标出是要删除的目标。
  2. 转为对应的红黑树
  3. 删除目标结点。
  4. 如果删的是父结点子结点上移补位。
  5. 补上来的结点染成原父结点的颜色。如果是根结点 直接填充黑色。(虽然单看234树转过来的这个局部,父结点必定是黑色。但在一个完整红黑中,父结点有可能是红色)

2. 删除3结点

删除一个元素,变成2结点。保持平衡。

  • 红结点:直接删除即可。
  • 黑结点:删除黑结点,红结点补位,并变成黑色。

  1. 原234树结点,蓝色 标出是要删除的目标。
  2. 转为对应的红黑树
  3. 删除目标结点。
  4. 如果删的是父结点子结点上移补位。
  5. 补上来的结点染成原父结点的颜色。如果是根结点 直接填充黑色

3. 删除2结点

删除结点后,当前位置空出,红黑树失去平衡。需要向父兄结点借元素借兵补充。

3.1. 兄弟是3或4结点

  1. 通过从兄弟节点借调元素,将2节点转变为3节点。(通过左旋右旋实现转变。)
  2. 然后按2、3节点规则删除目标。

3.2. 兄弟都是2结点,父是3或4结点

  1. 向父结点借来4,合并出新的结点(3,4,6)
  2. 4结点规则删掉目标。

3.3. 父兄结点都是2结点

  1. 向父借来元素,合并出新的4结点
  2. 4结点规则删掉目标。

如果当前是子树,则父结点需要递归向上借调。

总结

  1. 可以将红黑树看作是234树的一个具体实现。
  2. 一颗234树可以对应多个234树。(因为 3结点 对应 红黑树 时可以左倾,也可以右倾)

参考资料

笑虾:数据结构 - 学习笔记 - 红黑树
2-3-4 Trees

以上是关于数据结构 - 学习笔记 - 红黑树前传——234树的主要内容,如果未能解决你的问题,请参考以下文章

数据结构 - 学习笔记 - 红黑树

数据结构 - 学习笔记 - 红黑树

数据结构 - 学习笔记 - 红黑树

程序员内功心法(二叉树搜索树AVL树234树红黑树汇总)

基于234树手撕TreeMap红黑树源码(3万字长文带你走进红黑深处的细节)

红黑树探索笔记