当前课程知识点:数据结构(下) > 第七章 二叉搜索树 > (d2)AVL树:插入 > 07D2-1 插入:单旋
首先来考察插入操作的第一种情景
我们在某个节点原本已经更高的分支
插入了一个新的节点
这个分支的高度继续上升一层
从而导致它的平衡因子
从-1变成-2
突破了AVL树的底线
请注意 新的节点
可能插入在这儿
也可能插入在这儿
我们在它们之间引入一条虚线
表示二者只能取其中之一
而且我们假设g是所有因此
而发生失衡的祖先中
最深的那个
那么从g出发
沿着这个新增长的分支
我们可以找到它的孩子节点
以及孙子节点
我们将它们分别命名为v p和g
分别暗示着是一个节点
以及它的父亲parent
以及祖父grandparent
根据这样的命名方式 我们也不难理解
尽管一个节点的插入
有可能会导致多个祖先的失衡
其中最低的那个
也不会低于它的祖父辈
那么既然此处已经发生了失衡
我们又当如何令它重新恢复平衡呢?
实际上 我们能做的无非是上一节
所介绍的等价变换
也就是zig或者是zag旋转
在此处 我们只需要做一次旋转
也就是所谓的单旋
我们来通过下面这个动画
了解整个调整的过程
从我们刚才失衡的局部出发
接下来我们要围绕着
失衡的节点g
做一次逆时针的zag旋转
这样的一个旋转
可以由接下来的几步组合完成
首先引入一个临时的引用
指向节点p
接下来 我们要令p的左子树T1
成为g的右子树
为此我们只需这样调整
好
再接下来 我们要令g
成为p的左孩子
因此需要做这样的调整
再接下来 我们要将局部子树的根
由g替换为p 也就是说
我们要做这样的调整
好 此时的临时引用
也完成了历史使命
它可以退出了
而旋转操作
也同时宣告完成
至此重平衡化已经完成
为了更清楚地看到平衡化之后的效果
我们不妨对这个图稍事整理
不难验证 局部的这棵子树
的确已经恢复了平衡
然而好消息还不止一次
实际上 如果在此前g以上
还有其它的祖先
同时发生失衡
那么在这个局部重新恢复平衡之后
也会同时一揽子地重新获得平衡
你能看出这背后的原因吗?
在此你不妨暂停片刻
就这个问题做一思考
好的 我想你已经找到答案了
没错 在这里除了平衡因子以外
局部子树还有一个重要的指标
就是它的高度
那么 它的高度是在哪呢?
请留意这里我们所设置的三条基准线
不难发现 在插入新节点之前
原先这棵子树的高度
应该是以中间这条水平线为基准
然而对照重新平衡之后的
这棵树我们会发现
它的高度又重新地回到了
这样一条基准线上
这棵局部子树的高度能够复原
又意味着什么呢?
我们说这意义非常重大
这意味着它的所有祖先
在计算平衡因子时 所得的结果
也将与插入新节点之前 完全一样
换而言之
在局部子树高度复原之后
所有祖先也必然会
统一地恢复平衡
而全树呢 也将因此恢复平衡
请注意 对于这种情况
我们无非是做了一次zag旋转
这种旋转只涉及到局部的常数个节点
因此它所对应的时间消耗
应该是O(1)的
这个结果也再好不过了
当然这种情况只是所有情况中的一种
其特点是我们刚才所定义的gpv
这连续三代的节点
在方向上是朝向一致的
比如这里它们同时向右
所以我们也相应地称之为zag-zag
不难理解 对于对称的情况
也就是它们一致向左的情况
同样可以参照这种方法予以处理
那种情况我们也称作zig-zig
那么如果它们的朝向并不一致
而是呈所谓的之字形形式呢?
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-OJ系统说明
--关于OJ
--1-注册与登录
--2-界面与选课
--3-提交测试
-关于课程教材与讲义
--课程教材与讲义
-关于讨论区
--关于讨论区
-微信平台
--html
-PA晋级申请
--PA晋级
-(a)概述
--07A-1 纵览
--07A-5 接口
-(a)概述--作业
-(b1)BST:查找
-第七章 二叉搜索树--(b1)BST:查找
-(b2)BST:插入
-(b2)BST:插入--作业
-(b3)BST:删除
-第七章 二叉搜索树--(b3)BST:删除
-(c)平衡与等价
-(c)平衡与等价--作业
-(d1)AVL树:重平衡
-第七章 二叉搜索树--(d1)AVL树:重平衡
-(d2)AVL树:插入
-(d2)AVL树:插入--作业
-(d3)AVL树:删除
-(d3)AVL树:删除--作业
-(d4)AVL树:(3+4)-重构
-(d4)AVL树:(3+4)-重构--作业
-本章测验
--章节测验
-(a1)伸展树:逐层伸展
--习题
-(a2)伸展树:双层伸展
--习题
-(a3)伸展树:算法实现
--习题
-(b1)B-树:动机
--习题
-(b2)B-树:结构
--习题
-(b3)B-树:查找
--习题
-(b4)B-树: 插入
--习题
-(b5)B-树: 删除
--习题
-(xa1)红黑树:动机
--习题
-(xa2)红黑树:结构
--习题
-(xa3)红黑树:插入
--习题
-(xa4)红黑树:删除
-本章测验
--习题
-(b)散列:原理
--09B-3 数组
--09B-4 原理
--09B-5 散列
--09B-6 冲突
--习题
-(c)散列:散列函数
--习题
-(d1)散列:排解冲突(1)
--习题
-(d2)散列:排解冲突(2)
--习题
-(e)桶/计数排序
--习题
-本章测验
--本章测试
-(a1)需求与动机
--习题
-(a2)基本实现
--习题
-(b1)完全二叉堆:结构
--习题
-(b2)完全二叉堆:插入与上滤
--习题
-(b3)完全二叉堆:删除与下滤
--习题
-(b4)完全二叉堆:批量建堆
--习题
-(c)堆排序
--习题
-(xa1)左式堆:结构
--习题
-(xa2)左式堆:合并
--习题
-(xa3)左式堆:插入与删除
-本章测验
--本章测试
-(a)ADT
--习题
-(b1)串匹配
--习题
-(b2)蛮力匹配
--习题
-(c1)KMP算法:从记忆力到预知力
--习题
-(c2)KMP算法:查询表
--习题
-(c3)KMP算法:理解next[]表
--习题
-(c4)KMP算法:构造next[]表
--习题
-(c5)KMP算法:分摊分析
--习题
-(c6)KMP算法:再改进
-(d1)BM_BC算法:以终为始
-(d2)BM_BC算法:坏字符
-(d3)BM_BC算法:构造bc[]
-(d4)BM_BC算法:性能分析
-(e1)BM_GS算法:好后缀
-(e2)BM_GS算法:构造gs表
-(e3)BM_GS算法:综合性能
-(f1)Karp-Rabin算法:串即是数
-(f2)Karp-Rabin算法:散列
-本章测验
--本章测试
-(a1)快速排序:算法A
-- 12a1-5: 实例
--习题
-(a2)快速排序:性能分析
--习题
-(a4)快速排序:变种
-(b1)选取:众数
-(b3)选取:通用算法
--习题
-(c1) 希尔排序:Shell序列
--习题
-(c2)希尔排序:逆序对
-本章测验
--本章测试