数据结构 - 学习笔记 - 红黑树前传——234树
Posted 笑虾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构 - 学习笔记 - 红黑树前传——234树相关的知识,希望对你有一定的参考价值。
数据结构 - 学习笔记 - 红黑树前传——234树
简介
234树——234Trees
在学习红黑树
前需要先了解234树
。因为红黑树
就是由234树
演变出来的。(红黑树是234树的一种实现)
了解了234树
才能明白红黑树
颜色变化的底层逻辑。
- 明明是包含
123
个结点,为什么不叫123树
而叫234
树。我的理解是:因为树的特性就是分叉
,结点的命名是按它的分叉能力来的。n结点
就是能分n个叉
的结点。(吐槽:真是跟制动
有异曲同工之妙。) 234树
就是4阶B树
。也就是允许结点
最多有4个子结点
的平衡多路
查找树。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 |
红黑树对应关系
- 上图中没有画出具体的
子结点
仅用虚线框标识了一下子结点的取值范围。 - 不难看出,只要将
红黑树
中的红结点向上一提,与父结点合并,就反推出了234树
。 - 同时根据
3结点
的特性,可以看出234树
与红黑树
是一对多
的关系。 - 在平时分析
红黑树
时,可以直接在脑海里映射成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种红黑树情形
- 旋转方向的逻辑可以想象天平。
左边重
了往右挪(旋)
,右边重
了往左挪(旋)
。 - 从上图可以看到有
3
个位置能插入子结点
。对应6
种红黑树的情形。 - 其中有
2
种是平衡的,无需调整。剩下4种
需要通过旋转
实现平衡。
2.2. 有4种情形需要旋转
虽然共有4种
情形,但其中 LR
可以转为LL
, RL
可以转为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结点
与 红黑树
对应关系,罗列出来。根据新结点插入的位置不同,对应的红黑树也有所差异:
对应上图的步骤序号。
- 原234树为
357
. - 插入新元素。将要触发分裂。
- 先分裂。然后按新值大小,找到插入位置,与原有的
2结点
合并成为3结点
3.1. 中值上提为父结点,如果原本有父结点,分裂出去的结点,与原父结点合并。
3.2. 如果原来的父结点也是一个4结点
,将递归
触发分裂
。
3.3. 剩下两个结点,小的为左,大的为右。 234树
结点转红黑树
结点。
4.1. 所有2结点
变为黑色。
4.2.3结点
展开,上黑下红。
3.2. 触发分裂
单独分析一下触发分裂效果。
- 演示了从
234树
的角度来染色的逻辑(左)。 - 演示了从
红黑树
的角度来染色的公式
(右)。 - 如果当前操作的只是一颗
子树
。比如结点2
也是红色(需要旋转,对应RR
公式),则需要继续处理,直至根。
3.3.有4种情形需要变色实现平衡
- 【234树】 插入新元素。将要触发分裂。
- 【234树】 先分裂。然后找到待插入的目标位置,与原有的
2结点
合并成为3结点
- 【红黑树】 这是一个中间状态,为了便于观察才把它画出来。(
3结点
展开,但未调色,暂时还保持着不平衡的状态,便于观察) - 【红黑树】
父
结点、叔伯
结点变成黑色,祖父
结点变成红色。
4.1.父
结点与祖父
结点调换颜色:满足红结点子必黑的定义。同时对于插入新结点的这一路径来说黑结点数未发生变化。
4.2.叔伯
结点变成黑色:祖父
结点原本作为公共的黑结点,挪给左路后,右路就少了一个黑结点。因此叔伯
要站出来变黑维持平衡。 - 【红黑树】 最后
祖父
结点更新为当前结点。
5.1. 判断曾祖
是否为红色。如果是,则需要向上递归调整颜色,一直到根。
5.2. 如果是根,直接染黑。
3.4. 递归调整颜色
插入新结点 1
后递归触发变色。直到根结点为止。
删除逻辑
删除操作:根据删除目标所在位置不同,共有几种情况需要分别处理。
删除目标
为叶子结点
目标
在4结点中,删除后变成3结点。目标
在3结点中,删除后变成3结点。目标
是2结点,有三种情况:
3.1. 兄弟是3个结点
或4个结点
。
3.2. 两个兄弟结点都是2结点
,但父结点
是3结点
或4结点
。
3.3.兄弟结点
和父结点
都是2结点
。
- 如果
删除目标
非叶结点(有子结点)
- 找到
目标
的前驱
或后继
结点。前驱
或后继
必定是叶结点。 - 将
目标
值与前驱
或后继
交换。交换后目标
结点便是叶结点了。 - 按
叶结点
删除规则处理。
1. 删除4结点
删除一个元素,变成3结点
。保持平衡。
4结点
的删除,如果忽略掉它的兄弟结点。本质上还是一个3结点
的删除。
对应红黑树:
- 红结点:直接删除即可。
- 黑结点:删除黑结点,红结点补位,并变成黑色。
234树
结点,蓝色 标出是要删除的目标。- 转为对应的
红黑树
。 - 删除目标结点。
- 如果删的是
父结点
。子结点
上移补位。 - 补上来的结点染成原
父结点
的颜色。如果是根结点
直接填充黑色
。(虽然单看234树转过来的这个局部,父结点必定是黑色。但在一个完整红黑中,父结点有可能是红色)
2. 删除3结点
删除一个元素,变成2结点
。保持平衡。
- 红结点:直接删除即可。
- 黑结点:删除黑结点,红结点补位,并变成黑色。
原234树
结点,蓝色 标出是要删除的目标。- 转为对应的
红黑树
。 - 删除目标结点。
- 如果删的是
父结点
。子结点
上移补位。 - 补上来的结点染成原
父结点
的颜色。如果是根结点
直接填充黑色
。
3. 删除2结点
删除结点后,当前位置空出,红黑树失去平衡。需要向父兄
结点借元素借兵补充。
3.1. 兄弟是3或4结点
- 通过从兄弟节点借调元素,将
2节点
转变为3节点
。(通过左旋
或右旋
实现转变。) - 然后按
2、3节点
规则删除目标。
3.2. 兄弟都是2结点,父是3或4结点
- 向父结点借来
4
,合并出新的结点(3,4,6)
。 - 按
4结点
规则删掉目标。
3.3. 父兄结点都是2结点
- 向父借来元素,合并出新的
4结点
。 - 按
4结点
规则删掉目标。
如果当前是子树,则父结点需要递归
向上借调。
总结
- 可以将
红黑树
看作是234树
的一个具体实现。 - 一颗
234树
可以对应多个234树
。(因为3结点
对应红黑树
时可以左倾,也可以右倾)
参考资料
笑虾:数据结构 - 学习笔记 - 红黑树
2-3-4 Trees
以上是关于数据结构 - 学习笔记 - 红黑树前传——234树的主要内容,如果未能解决你的问题,请参考以下文章