当前课程知识点:数据结构(下) > 第七章 二叉搜索树 > (d3)AVL树:删除 > 07D3-1 删除:单旋
再来考察AVL树节点删除算法
比如这就是在节点删除之后
引起失衡的一种情况
如果我们同样地将
失衡的那个祖先命名为g
那么它之所以在此时会失衡
是因为此前所摘除的那个节点
恰好处于它原本就更短的那个分支
比如说T3的底部
也就是说 它的平衡因子
将由此前的+1变成现在的+2
从而违规
请注意 这里子树T0和T1的底部
应该至少有一个节点
而T2底部的这个节点有可能存在
也有可能不存在
请注意 与插入的情况不同
在这里 失衡节点g有可能恰好就是
刚刚被删除这个节点的父亲
然而无论如何 只要g p v
这祖孙三代的节点是朝一个方向排列的
比如 p是g的左孩子 v也是p的左孩子
那么我们就可以通过一次单旋
来恢复局部的平衡
具体来说 也就是围绕这个失衡的节点g
做一次顺时针的zig旋转
这个旋转操作的细节
在此前插入算法中
我们已经给出过详细的动画演示
所以这里我们不妨
直接给出旋转调整之后的结果
可以看到 局部的子树树根
由原先的g替换成了p
而节点v和g
则分别成为了节点p的左右孩子
不难验证 经过这样一个调整之后
在此局部 的确恢复了平衡
那么故事就此终结了吗?
我们说有的时候是 有的时候不是
这里的关键在于 T2这棵子树
底层那个节点是否存在
如果它存在 那么我们会发现
经过这样的调整之后
子树的新高度
与此前原树的高度是一样的
因此与插入算法同理
在这种情况下 我们可以保证
在这棵子树以上的每一个祖先
它们的高度及平衡因子
都会继续保持原状
因此不会发生新的失衡现象
然而问题在于T2的这个底层节点
有可能根本就不存在
在这样的一个情况下
相对于原树的高度
调整之后新树的高度
会缩短一个单位
此时不妨设想这样一个场景
也就是某一个祖先
它的另一个分支可能会更高
换而言之 它此前的平衡因子已经是-1
因此在原本就更短的左侧分支
进一步缩短之后
它的平衡因子将进一步下降到-2
从而超标
请注意这个节点在我们调整之前
原本是平衡的
而在它下属的后代恢复平衡之后
它却有可能既而失衡
我们也可以等效地认为
这个节点的失衡
是由于为了消除它后代的失衡
进而引发的
这样一种失衡逐渐向上层祖先传播的现象
也是删除操作所特有的
当然从算法而言
这并不是什么了不起的事情
因为对于这个新的失衡祖先
我们完全可以套用整个调整算法
继续使它复衡
当然 因此有可能又会引发
更高层祖先的失衡
极端的情况下
我们有可能会在每一层都进行一次调整
累计而言 这种调整可能会多达logn次
需要指出的是 这样一种估计
既不是杞人忧天 更不是危言耸听
我们的确可以构造出这样的反例
关于这一点 你可以参考教材
配套习题解析中的[7-17]题
当然 与插入算法一样
我们还需要考虑另外一种情况
也就是g p v这样连续三代节点
未必是朝一个方向排列的
如果它们是按照所谓的之字形排列呢?
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)希尔排序:逆序对
-本章测验
--本章测试