当前课程知识点:数据结构(下) > 第七章 二叉搜索树 > (d1)AVL树:重平衡 > 07D1-5 失衡+复衡
考察这样一个实例
首先请关注中间的这棵BST
不难发现 它其实就是
我们在开篇所举的那个AVL树实例
只不过在这里我们将数字的关键码
统一替换为了字母
接下来 我们假设需要插入M
那么按照BST的常规算法
经过适当的搜索
我们可以确定应该将M
作为K的右孩子接入到这棵树中
然而我们随后会发现
M的介入
虽然不致引起它的父亲K的失衡
却导致它的祖父N因此失衡
更糟糕的是
它的曾祖父 也就是R
也会因为它的插入
而导致失衡
而作为一个极端的例子
这里使得它的更高层祖先
也会因为它的插入而失衡
总而言之 在一棵AVL树中
插入一个节点之后
有可能会导致若干个祖先失衡
当然你大可放心
除了祖先之外的其它节点
是不可能失衡的
其背后的原因在于
对于非新插入节点
祖先的那些节点而言
无论是它们的高度
还是它们孩子的高度
都不会因为新节点的插入而有所变化
所以它们各自的平衡因子
也都将维持原状
如果此前是平衡的
那么它们就不可能变成失衡
好
我们再来看另一个方向的操作
假设在原先的这棵AVL树中
我们删除了某一个节点
比如Y
那么类似地 我们也会发现
Y的删除会导致它此前的
那个父节点R发生失衡
你会发现 除了R之外
Y此前的其余祖先 比如说G
并未失衡
这只是一种巧合
或者是我们没有考虑到
最坏的情况吗?
我们说不是这样的
因为对于删除操作来说
在摘除节点之后的瞬间
至多只有一个节点会失衡
这背后是什么原因呢?
不妨假设 在某个节点被摘除之后
的确会引起它的某个
甚至某些祖先发生失衡
我们可以证明
其实其中只有一个祖先会失衡
为此我们不妨考察
其中高度最低的那个失衡祖先
我们会发现
这个祖先尽管失衡了
它的高度却必然保持原样
这背后的原因在于
如果这个节点的失衡的确是因为
它的某个后代被摘除了
那么这个后代在此前
也必然属于它那个相对更短的分支
而它的高度则是由它
相对更长的那些分支所决定的
因此这个节点的删除
并不致于引起这个祖先高度的变化
而既然这个祖先的高度不致于变化
那么相对于更高的祖先而言
它们在计算平衡因子时
结果也应该与
未删除节点之前是一样的
换而言之 它们也必然是平衡的
所以概括而言
如果在一棵AVL树中
删除某个节点之后
的确引起祖先的失衡
那么这种失衡的祖先
充其量不过只有一个
没错
在某个节点删除之后的瞬间
至多只有一个祖先失衡
而反过来 我们却刚刚看到
一个节点的插入
却有可能引起几乎所有的祖先
同时失衡
那么我们是否可以说
相对而言
AVL树的删除操作
要比插入操作更为简单呢?
实际情况 恰恰相反
如果我们将插入操作和删除操作
比喻为孩子
那么插入操作是这样一种孩子
他有可能在某个时候
会闯下一连串的祸
但这个孩子还至少是一个好孩子
因为他能够痛改前非
我们很快就会看到
一旦他能够改正其中的一个错误
那么其它的一连串错误
也都会自然地烟消云散
而反过来 删除操作呢
虽然不能称作是一个坏孩子
但是他至少是一个不长记性
不吸取教训的孩子
我们很快就会看到
尽管这个孩子在每一次
只会闯下一个祸
但是每当你帮助他
改正了这个错误之后
他转眼就会忘掉这件事
并且很快又会在另一个位置
犯下同一样的错误
而且这个孩子的记忆力糟糕之极
即便你有足够的耐心
帮助他改正下一个错误
接下来转眼之间
他又有可能在另一个位置
再次犯下同样的错误
因此相对而言
插入操作实际上要更为简便一些
而删除操作要复杂不少
因此接下来
我们不妨从插入操作入手
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)希尔排序:逆序对
-本章测验
--本章测试