【数据结构】考研数据结构核心考点:AVL树插入操作深度解析——从理论到实践的旋转平衡实现
AVL树插入操作
- 导读
- 一、LL平衡旋转
- 1.1 基本定义
- 1.2 右单旋转过程
- 1.3 满足LL旋转的AVL树判断
- 1.4 小结
- 二、RR平衡旋转
- 2.1 基本定义
- 2.2 左单旋转过程
- 2.3 满足RR旋转的AVL树判断
- 2.4 小结
- 三、LR平衡旋转
- 3.1 基本定义
- 3.2 先左后右旋转过程
- 3.3 满足LR旋转的AVL树判断
- 3.4 小结
- 四、RL平衡旋转
- 4.1 基本定义
- 4.2 先右后左双旋转过程
- 4.3 满足RL旋转的AVL树判断
- 4.4 小结
- 五、小结
- 结语
导读
大家好,很高兴又和大家见面啦!!!
在上一篇内容中我们深入探讨了AVL树的核心特性——通过平衡因子(左子树高度减去右子树高度)来维护二叉搜索树的平衡。
其中有三个重要内容:
- 平衡条件:AVL树要求每个节点的平衡因子绝对值不超过1
- 失衡判断:当插入/删除操作导致平衡因子变为±2时,树失去平衡
- 最小不平衡子树:调整总是从最靠近新插入节点的失衡子树开始
理解了AVL树的平衡原理后,接下来最关键的问题就是——当插入操作破坏平衡时,我们如何通过高效的旋转操作让树恢复平衡?这就是本文要深入解析的核心内容。
本文将系统讲解AVL树的四种旋转调整策略,通过丰富的图示和具体场景分析,带你掌握:
🔹 LL旋转(右单旋):处理"左孩子的左子树"插入导致的失衡
🔹 RR旋转(左单旋):解决"右孩子的右子树"插入问题
🔹 LR旋转(先左后右):应对"左孩子的右子树"插入的复合情况
🔹 RL旋转(先右后左):处理"右孩子的左子树"插入的双重调整
每种旋转都配有多角度图示演示和严格的判断条件说明,特别是通过对比分析帮你精准识别不同失衡场景对应的解决方案。文末的总结表格将四种情况对比展示,方便快速查阅应用。
无论你是正在学习数据结构的学生,还是准备面试的开发者,这篇内容都将帮你建立完整的AVL树平衡调整知识体系。接下来让我们从最简单的LL旋转开始,逐步攻克AVL树插入操作的所有难点!
一、LL平衡旋转
1.1 基本定义
LL平衡旋转(右单旋转):在结点 A
的左孩子(LLL)的左子树(LLL)上插入了新结点,使得 A
的平衡因子由 111 增至为 222 ,导致以 A
为根结点的子树失去平衡,需要一次向右的旋转操作。
1.2 右单旋转过程
下面我们以图示为例进行说明:
从上图中我们可以看到,当我们对结点 A
的左孩子(以结点 B
为根结点的子树)的左子树(以结点 D
为根结点的子树)中插入一个新的结点 F
后,各子树的平衡因子均发生了改变:
- 以结点
D
为根结点的子树的平衡因子由原先的 000 ,变为了 111 或 −1-1−1 - 以结点
B
为根结点的子树的平衡因子由原先的 000,变为了 111 - 以结点
A
为根结点的子树的平衡因子由原先的 111,变为了 222
可以看到,此时的最小不平衡子树是以结点 A
为根结点的子树,我们需要将该子树向右旋转一次,即:由以 A
为根结点调整为以 B
为根结点:
当结点 B
成为树的根结点后,结点 A
就转变为了该结点的孩子结点。从图中可以看到,此时结点 B
的孩子有3个,因此,现在的树并不是一棵二叉树。
为了让树恢复成一棵二叉树,那么我们就需要处理结点 B
最开始的右孩子结点 E
。
当我们对右旋之前的 BST 进行中序遍历,我们可以得到一个递增序列:
F < D < B < E < A < C
可以看到,结点 B
、结点 E
与结点 A
之间的关系为 B < E < A
,因此,对于结点 E
而言,当作为结点 B
的孩子结点时,是其右孩子,当作为结点 A
的孩子结点时,是其左孩子;
那也就是说,如果我们希望在完成一次右单旋转后,还能保持该树为二叉树的话,我们还需要将结点 B
的右孩子结点 E
更新为结点 A
的左孩子:
1.3 满足LL旋转的AVL树判断
右单旋转的过程相信大家应该都理解了,不知道大家有没有考虑过一个问题:
- 满足右单旋转的二叉树,是否一定是上述这种情况?
这里我们来看看几种可能得二叉树:
- 结点
B
只有左孩子的二叉树
从该二叉树中的各结点的平衡因子我们不难发现,该树也是一棵 AVL树 ,当我们对该树根结点 A
的左孩子 B
的左子树 D
上插入一个新结点时,该棵树就变为了下面这棵二叉树:
可以看到,此时的根结点 A
的平衡因子因为新结点的插入而从 111 变成了 222 ,那么我们是不是也需要通过右单旋转使其变成 AVL树 呢?
答案是不行。这是因为在前面我们就说明,AVL树 的调整是对最小平衡子树的调整。而在上述的二叉树中,其最小平衡子树是以结点 B
为根的子树:
我们真正要进行调整的是该棵子树,而不是以结点 A
为根的二叉树。因此要进行右单旋转的 AVL树 不可能是这种情况,也就是说,根结点 A
的左孩子 B
的左孩子高度不能高于右孩子;
- 结点
A
的右孩子存在子树
当我们在结点 A
的左孩子 B
的左子树 D
中插入一个新结点,那么该树就变为了下面这棵树:
当新结点插入后,结点 A
的平衡因子从 000 变为 111 ,此时该树还是一棵 AVL树 ,也就不需要进行调整。因此要进行右单旋转的 AVL树 也不是这种情况,也就是说,结点 A
的左孩子高度一定比右孩子高度多1,即需要调整的 AVL树 一定是平衡因子为 111 的 AVL树;
- 结点
B
的右孩子存在子树
这里需要注意,为了保证该树满足 AVL树 的要求,那么根结点
A
的右孩子C
至少有一个孩子,即其平衡因子即可以是 111 或 −1-1−1 ,也可以同时拥有左孩子与右孩子,即平衡因子可以是 1、−11、-11、−1 或者 000 。
这里我们展示的是拥有1个孩子的情况
当我们在结点 A
的左孩子 B
的左子树 D
中插入一个新结点,那么该树就会变为下面这棵树:
当插入新结点后,根结点 A
的平衡因子并没有发生任何变化,因此需要进行调整的 AVL树 一定不是这种情况,也就是说结点 A
的左孩子 B
的右孩子高度不能高于左孩子
1.4 小结
整理一下上述的所有情况,我们就得到了需要进行 LL平衡旋转 的 AVL树 一定满足以下情况:
- 根结点的平衡因子一定为 111,即左孩子的高度一定比右孩子的高度大1
- 根结点的左孩子的平衡因子一定为 000 ,即左子树的高度与右子树的高度一致
- 根结点的右孩子的高度一定与根结点的左孩子的左右子树高度相等
那么满足以上两点的 AVL树 我们可以表示为:
当完成一次右单旋转后,该树的根结点会更新为原根结点 A
的左孩子 B
,原根结点 A
则会变为新根结点 B
的右孩子,而新根结点 B
的原右孩子 E
会更新为新右孩子 A
的左孩子:
这里我们需要注意,根结点的右子树高度:hhh 可以为 0,即:
当我们对该树进行 LL插入结点时,整个树会更新为:
此时的二叉树是一棵以结点 A
为最小不平衡子树的二叉树,那么在我们对其进行一次右单旋转后,就得到了新的 AVL树:
因此我们在判断一棵最小不平衡二叉树是否需要进行LL平衡旋转时,我们需要从以下几点出发:
- 导致失衡的结点是否为根结点的左孩子的左子树
- 去掉失衡结点后的子树是否满足LL旋转的条件:
- 根结点的平衡因子为 111
- 根结点左孩子的平衡因子为 000
- 根结点的右孩子、左孩子的左子树以及左孩子的右子树这三棵子树的高度均相等
当满足上述条件时,则说明该最小不平衡子树需要通过一次右单旋转来重新达到平衡;
二、RR平衡旋转
2.1 基本定义
RR平衡旋转(左单旋转):在结点 A
的右孩子(RRR)的右子树(RRR)上插入了新结点,使得 A
的平衡因子由 −1-1−1 减至为 −2-2−2 ,导致以 A
为根结点的子树失去平衡,需要一次向左的旋转操作。
2.2 左单旋转过程
下面我们以图示进行说明:
当插入这个新结点后,各子树的平衡因子发生了变化:
- 以结点
E
为根结点的子树的平衡因子由 000 变为了 111 或 −1-1−1 - 以结点
C
为根结点的子树的平衡因子由 000 变为了 −1-1−1 - 以结点
A
为根结点的子树的平衡因子由 −1-1−1 变为了 −2-2−2
可以看到,此时的最小不平衡子树是以结点 A
为根结点的子树,我们需要将该子树向左进行一次旋转操作,使得树的根结点由结点 A
更新为结点 C
:
与右单旋转一样,在进行左单旋转后,我们同样需要将新根结点 C
的原左孩子 D
更新为新左孩子 A
的右孩子:
2.3 满足RR旋转的AVL树判断
与右单旋转一样,并不是任意一棵 AVL树 在对根结点的右孩子的右子树插入一个新结点后,都需要进行一次左单旋转。
左单旋转我们可以视为右单旋转的镜像旋转,因此我们可以通过右单旋转的判断条件来推出左单旋转的判断条件:
- 根结点
A
的右孩子高度一定比左孩子高度高1 - 根结点
A
的右孩子C
的左右子树高度一定相等,且一定等于根结点A
的左孩子B
的高度
2.4 小结
判断一棵最小不平衡子树是否需要采用 RR旋转来达到平衡,我们需要从以下角度出发:
- 判断导致不平衡的结点是否为最小不平衡子树中,根结点的右孩子的右子树中的结点
- 去掉该结点后,该子树是否满足 RR平衡旋转的要求:
- 根结点的平衡因子为:−1-1−1
- 根结点的右孩子的平衡因子为:000
- 根结点的左孩子,根结点的右孩子的左子树以及根结点的右孩子的右子树这三棵子树的高度相等
当满足上述条件时,说明该最小不平衡子树需要通过一次左单旋转来重新达到平衡。
三、LR平衡旋转
3.1 基本定义
LR平衡旋转(先左后右双旋转):在结点 A
的左孩子(LLL)的右子树(LLL)上插入了新结点,使得 A
的平衡因子由 111 增至为 222 ,导致以 A
为根结点的子树失去平衡,需要两次旋转操作——先左单旋转,再右单旋转。
3.2 先左后右旋转过程
下面我们以图示为例进行说明:
当插入这个新结点后,各子树的平衡因子发生了变化:
- 以结点
E
为根结点的子树的平衡因子由 000 变为了 111 或 −1-1−1 - 以结点
B
为根结点的子树的平衡因子由 000 变为了 −1-1−1 - 以结点
A
为根结点的子树的平衡因子由 111 变为了 222
可以看到,此时的最小不平衡子树是以结点 A
为根结点的子树,我们需要将该子树的左孩子 B
的右子树 E
进行一次旋转操作,使得树的根结点 A
的左孩子 B
更新为结点 C
:
当完成了这次的左单旋转后,此时的最小不平衡子树就满足了 LL旋转的条件:
- 导致不平衡的结点
D
与EL
位于根结点A
的左孩子E
的左子树B
中 - 去掉该结点后,子树满足以下条件:
- 根结点
A
的平衡因子为 111 - 根结点
A
的左子树E
的平衡因子为 000 - 根结点
A
的右孩子C
、根结点A
的左孩子E
的左子树B
以及根结点A
的左孩子E
的右子树F
,这三棵子树的高度均相等,均为1
- 根结点
因此为了将这棵树恢复平衡,我们需要对其进行一次右单旋转:
3.3 满足LR旋转的AVL树判断
同样的,并不是所有的 AVL树 在插入新结点导致失衡后,都可以通过 LR旋转来使其恢复平衡的,我们可以根据以下几点进行判断:
- 该子树是否满足 LL旋转 的判断条件:
- 根结点
A
的左子树高度比右子树高度高 111 - 根结点
A
的左子树B
的左右子树高度相等,且等于根结点A
的右子树C
的高度
- 根结点
- 插入的新结点位于根结点左孩子的右子树
3.4 小结
LR旋转实际上是从 LL旋转中变化而来,当失衡前的 AVL树 满足以下条件:
- 根结点的平衡因子为:111
- 根结点左孩子的平衡因子为:000
- 根结点左孩子的左右子树高度相等,且等于根结点右孩子的高度
此时当插入的新结点导致子树失衡时,会出现以下两种情况:
- 新结点位于根结点
A
的左孩子B
的左子树D
中,则需要通过LL旋转恢复平衡; - 新结点位于根结点
A
的左孩子B
的右子树E
中,则需要通过LR旋转恢复平衡;
四、RL平衡旋转
4.1 基本定义
RL平衡旋转(先右后左双旋转):在结点 A
的右孩子(RRR)的左子树(LLL)上插入了新结点,使得 A
的平衡因子由 −1-1−1 减至为 −2-2−2 ,导致以 A
为根结点的子树失去平衡,需要两次旋转操作——先右单旋转,后左单旋转。
4.2 先右后左双旋转过程
下面我们以图示为例进行说明:
当插入这个新结点后,各子树的平衡因子发生了变化:
- 以结点
D
为根结点的子树的平衡因子由 000 变为了 111 或 −1-1−1 - 以结点
C
为根结点的子树的平衡因子由 000 变为了 111 - 以结点
A
为根结点的子树的平衡因子由 111 变为了 −2-2−2
可以看到,此时的最小不平衡子树是以结点 A
为根结点的子树,我们需要将该子树的右孩子 C
的左子树 D
进行一次旋转操作,使得树的根结点 A
的右孩子 C
更新为结点 D
:
当完成了这次的右单旋转后,此时的最小不平衡子树就满足了 RR旋转的条件:
- 导致不平衡的结点
E
与DR
位于根结点A
的右孩子D
的右子树C
中 - 去掉该结点后,子树满足以下条件:
- 根结点
A
的平衡因子为 −1-1−1 - 根结点
A
的右子树D
的平衡因子为 000 - 根结点
A
的左孩子B
、根结点A
的右孩子D
的左子树DL
以及根结点A
的右孩子D
的右子树C
,这三棵子树的高度均相等,均为1
- 根结点
因此为了将这棵树恢复平衡,我们需要对其进行一次左单旋转:
4.3 满足RL旋转的AVL树判断
同样的,并不是所有的 AVL树 在插入新结点导致失衡后,都可以通过 RL旋转来使其恢复平衡的,我们可以根据以下几点进行判断:
- 该子树是否满足 RR旋转 的判断条件:
- 根结点
A
的右子树高度比左子树高度高 111 - 根结点
A
的右子树C
的左右子树高度相等,且等于根结点A
的左子树B
的高度
- 根结点
- 插入的新结点位于根结点右孩子的左子树
4.4 小结
RL旋转实际上是从 RR旋转中变化而来,当失衡前的 AVL树 满足以下条件:
- 根结点的平衡因子为:−1-1−1
- 根结点右孩子的平衡因子为:000
- 根结点右孩子的左右子树高度相等,且等于根结点左孩子的高度
此时当插入的新结点导致子树失衡时,会出现以下两种情况:
- 新结点位于根结点
A
的右孩子C
的左子树D
中,则需要通过RL旋转恢复平衡; - 新结点位于根结点
A
的右孩子C
的右子树E
中,则需要通过RR旋转恢复平衡;
五、小结
当我们在对失衡的 BST 进行旋转判断时,我们主要通过以下方面进行判断:
- 树形
- LL型与LR型
- RR型与RL型
- 插入位置
- LL型与LR型中,进行LL插入,通过LL旋转恢复平衡
- LL型与LR型中,进行LR插入,通过LR旋转恢复平衡
- RR型与RL型中,进行RR插入,通过RR旋转恢复平衡
- RR型与RL型中,进行RL插入,通过RL旋转恢复平衡
结语
今天的内容到这里就全部结束了,通过今天的学习,我们系统掌握了AVL树插入操作的核心技术——四种旋转平衡策略。让我们回顾一下重点内容:
核心收获:
-
🔁 单旋转:LL型(右旋)与RR型(左旋)适用于插入方向一致的简单失衡
-
🔄 双旋转:LR型(先左后右)与RL型(先右后左)处理交叉插入的复杂情况
-
🎯 判断关键:通过分析“最小不平衡子树”的树形结构和插入位置,精准选择旋转策略
-
💡 实战技巧:文末的对比表格为你提供了快速判断的决策指南
特别提醒:本文配有的20+张手绘流程图是理解旋转过程的“可视化秘籍”,建议结合文字说明反复对照学习,直到能够独立画出每种旋转的完整过程。
如果这篇近万字的详解对你理解AVL树有帮助,欢迎:
⭐ 点赞 - 让我知道这个方向对你有价值
📚 收藏 - 随时回顾这一数据结构重要考点
🔄 转发 - 帮助更多正在啃算法的伙伴
💬 评论 - 说说你学习中的困惑或成功体验
下篇预告:我们将深入探讨AVL树的删除操作——这比插入更复杂但也更有挑战性!关注我,不错过后续精彩内容。
一起成长:无论是数据结构考试、面试准备还是技能提升,坚持学习算法的你正在变得更强!感谢各位的阅读与支持,我们下一篇再见!