👋 Hi, I’m @Beast Cheng
👀 I’m interested in photography, hiking, landscape…
🌱 I’m currently learning python, javascript, kotlin…
📫 How to reach me --> 458290771@qq.com
喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。🧑💻
感兴趣的小伙伴可以点一下订阅、收藏、关注!🚀
谢谢大家!🙏
定义
平衡二叉树(Balanced Binary Tree),简称平衡树(AVL树)
树上任一结点的左子树和右子树的高度之差不超过 1
结点的平衡因子 = 左子树高 - 右子树高
平衡因子只可能是:
0
,
∣
1
∣
0,|1|
0,∣1∣
插入
每次调整的对象都是“最小不平衡子树 ”
在插入操作中,只要将最小不平衡子树调整平衡,则其他祖先结点都会恢复平衡
调整最小不平衡子树
LL:在A的左孩子的左子树中插入导致不平衡
目标:
- 恢复平衡
- 保持二叉排序树特性
方法:
LL平衡旋转(右单旋转)。由于在结点A的左孩子(L)的左子树(L)上插入了新节点,A的平衡因子由 1 增至 2,导致以A为根的子树失去平衡,需要一次向右的旋转操作。将A的左孩子B向右上旋转代替A称为根结点,将A结点向右下旋转称为B的右子树的根结点,而B的原右子树则作为A结点的左子树
RR:在A的右孩子的右子树中插入导致不平衡
左旋
LL 和 RR 的代码思路
右旋:
实现 f 向右下旋转,p 向右上旋转,其中 f 是 爹,p 为左孩子, gf 为 f 他爹
f->lchild = p->rchild
p->rchild = f
gf->lchild/rchild = p
左旋:
实现 f 向左下旋转,p 向左上旋转,其中 f 是 爹,p 为左孩子, gf 为 f 他爹
f->rchild = p->lchild
p->lchild = f
gf->lchild/rchild = p
LR:在A的左孩子的右子树中插入导致不平衡
pass
RL:在A的右孩子的左子树中插入导致不平衡
pass
练习
1
2
3
查找效率分析
若树高为 h,最坏情况下,查找一个关键字最多需要对比 h 次,即查找操作时间复杂度不可能超过 O ( h ) O(h) O(h)
平衡二叉树最大深度为 O ( l o g 2 n ) O(log_2n) O(log2n) ,平均查找长度/查找的时间复杂度为 O ( l o g n ) O(log n) O(logn)
插入和删除
插入:
- 插入新节点后,要保持二叉排序树的特性不变(左 < 中 < 右)
- 若插入新节点导致不平衡,则需要调整平衡
删除:
- 删除节点后,要保持二叉排序树的特性不变(左 < 中 < 右)
- 若删除节点导致不平衡,则需要调整平衡
删除操作具体步骤:
- 删除节点
- 若删除的节点是叶子结点,直接删
- 若删除的节点只有一个子树,用子树顶替删除位置
- 若删除的节点有两棵子树,用前驱(或后继)结点顶替,并转换为对前驱(后继)结点的删除
- 一路向上找到最小不平衡子树,找不到就结束
- 找最小不平衡子树下,“个头”最高的儿子、孙子
- 根据孙子的位置,调整平衡(LL、RR、LR、RL)
- 孙子在LL:儿子右单旋
- 孙子在RR:儿子左单旋
- 孙子在LR:孙子先左旋,再右旋
- 孙子在RL:孙子先右旋,再左旋
- 如果不平衡向上传导,继续②
- 对最小不平衡子树的旋转可能导致树变矮,从而导致上层祖先不平衡