平衡二叉树(AVL)详解

平衡二叉树(AVL)

1、为什么会出现平衡二叉树
1.1、什么是二叉树

二叉树特点是每个结点最多只能有两棵子树,且有左右之分。

性质

  • 二叉树的第i层上至多有2 ^ (i - 1)(i≥1)个节点
  • 深度为h的二叉树中至多含有2^h - 1 个节点
  • 若在任意一棵二叉树中,有n0个叶子节点,有n2个度为2的节点,则必有n0 = n2+1
  • 具有n个节点的完全二叉树深为 log2^x + 1(其中x表示不大于n的最大整数)
1.2、什么二叉查找树

二叉查找树(Binary Search Tree),(又:二叉搜索树二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树

性质

  • 若任意结点的左子树不空,则左子树上所有结点的值均不大于它的根结点的值。

  • 若任意结点的右子树不空,则右子树上所有结点的值均不小于它的根结点的值。

  • 任意结点的左、右子树也分别为二叉搜索树 。

缺点

插入1,2,3,4,5这几个数,生成的二叉搜索树为:

在这里插入图片描述

查找的速度并不可以得到提高还为o(logn),所以引出来了我们今天要讲解的平衡二叉树。

平衡二叉树(Balanced Binary Tree),又称AVL树,指的是左子树上的所有节点的值都比根节点的值小,而右子树上的所有节点的值都比根节点的值大,且左子树与右子树的高度差最大为1。

平衡二叉树性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

知道了平衡二叉树的概念之后,我们来聊聊为什么会出现这种数据结构?

之前我们已经介绍过了二叉树,我们我们知道了二叉树有一定的缺点,不如我们在查找的时候必须把全部的节点全部遍历一遍,但是平衡二叉树会缩小范围,因为左边的都比根小,右边的都比跟大。

平衡因子(BF):节点的左右子树的高度和高度差。根据平衡二叉树的概念可知,平衡因子的取值只能为【-1,0,1】(左-右 或者 右-左 都可以,下面采取的为 右-左)

2、平衡二叉树的插入操作
  1. 插入前是一个 AVL + 搜索特性 的二叉树

  2. 先不考虑插入后是否满足特性,不满足时会进行修复

  3. 插入完毕后,得到的还应该是一个满足 AVL + 搜索的二叉树

定义节点:

class Node<K,V> {
    private K key;
    private V value; // K-V 模型带着 value ,纯 K 模型,可以不带 value
    
    Node<K,V> left;
    Node<K,V> right;
    
    int bf; // 平衡因子
    Node<K,V> parent; // 保存自己的双亲节点,如果是根,则是null
}

先定义原来的树

2.1、按照普通搜索树的方式进行插入

  1. 如果 key 已经存在,则放弃插入

  2. 通过查找,找到 4 理论上应该在的位置

  3. 把 4 插入到理论的位置,并且调正平衡因子

2.2、设置 + 修改平衡因子
  • cur 的平衡因子一定是 0

  • 思考谁的平衡因子需要修改? 答案是parent

    • 如果 cur 是parent 的右孩子,parent.bf = parent.bf + 1;
    • 如果 cur 是parent 的左孩子,parent.bf = parent.bf - 1;
    • parent.bf 被修改后的值可能是多少?【-2,-1,0,1,2】

    下面我们就根据parent.bf的取值分类 讨论下怎么调整可以使这棵树,使它 满足 平衡二叉树的条件!

1、被修改后的bf = 0

则可以得出 H(parent) 这棵树的高度没有变化

因为 H(parent) 没有变,所以 不会影响 parent.parent 的平衡因子

所以,插入过程结束后(整棵树的 bf 都是正确的,并且满足 AVL 树的特性)

举例:

2、被修改后的bf=1or-1

这个结果说明H(parent)增加了 1

因为 parent 的高度变了(增加了 1 ),所以 parent.parent 的平衡因子也需要调整

只要 bf 调节完的结果是 -1/1 ,则调整 bf 的过程会向上蔓延,直到遇到 0 或者 遇到 -2/2 并进行修复 或者遇到 root

2、被修改后的bf=2or-2

需要利用规则进行修复,使得 继续满足 AVL 树的特性

在讲这个规则之前,我们先来思考一个问题:

在修复之前,例如 parent.bf = 2,问其他位置的 bf 有可能也会破坏性质吗?

答案是不会的。任意时刻,一个 AVL树 最多只会有一个节点的 BF 不满足性质

AVL 把 破坏规则的情况叫做失衡(失去平衡)

失衡分为四种:

左左失衡 / 左右失衡 / 右右失衡 / 右左失衡

1、左左失衡:parent 的失衡是因为在 parent 的左孩子 的左子树中插入导致的失衡

2、左右失衡: parent 的失衡 是因为在 parent 的左孩子的右子树中插入导致的失衡

3、右右失衡:parent 的失衡是因为在 parent 的右孩子的右子树中插入导致失衡

在这里插入图片描述

右左失衡:parent 的失衡是因为 在parent的右孩子的左子树插入导致的失衡

我们已经了解了几种失衡了,那么怎么解决呢失衡问题呢?

1、左左失衡:只需要对 parent(失衡的节点)进行右旋即可

举例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bmb9lQac-1586011222269)(C:\Users\惠秋丽\Desktop\1586007561716.png)]

证明为什么右旋可以解决左左失衡问题?

在这里插入图片描述

根据搜索的性质,可以得出:

K(甲) < K(B) < K(乙) < K(A) < K(丙)


我们假设 H(丙) = X,并且 BF(A) = -2

我们可以得出 H(B) = X+1

思考:H(乙) 可以为 X+1 吗?答案是不可以,因为如果 H(乙) = X+1 的话,就代表还没插入节点就已经失衡了,并不是因为插入了节点才失衡了,所以 只能 H(甲) = X + 1

思考:H(乙) 可以为 X-1或者更小 吗?答案是不可以,因为如果 H(乙) = X - 1 的话,就是 B 这个节点是不平衡,就轮不到 解决 A 的失衡问题了


修复:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WqjHX3SD-1586011222274)(C:\Users\惠秋丽\Desktop\1586008289231.png)]

  • 插入前 H(A) = X + 2,插入+旋转后 H(B) = X + 2

  • 修复后:满足:

    1. 修复后是否仍然满足搜索树的特征
    2. 修复后是否仍然满足AVL的特征
    3. 修复后,树的整体是不是不变

2、左右失衡:先对 cur 进行左旋,再对 parent 进行右旋

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M4H6BiJc-1586011222277)(C:\Users\惠秋丽\Desktop\1586008706804.png)]

证明:

根据搜索的性质,可以得出:

K(甲) < K(B) < K(Z) < K© < K(丙) < K(A) < K(丁)


假设:H(丁) = X ,那么 H(B) = X + 2

则,H(甲) 一定 X ,原因同上

H© 一定为 X + 1

下面我们来看看 H(乙) 和 H(丙)

1、首先他们之间有一个H为 X

2、如果插入的节点在乙子树中,则插入后 H(乙) = X,H(丙) = X - 1;

​ 如果插入的节点在丙子树中,则插入后 H(丙) = X,H(乙) = X - 1;

这里面的原因可以利用反证法来证明。把前面左左失衡理解了,这里和左左失衡的道理是一样的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RDHwoZWj-1586011222282)(C:\Users\惠秋丽\Desktop\1586010347753.png)]

修复后,满足:

  1. 修复后是否仍然满足搜索树的特征
  2. 修复后是否仍然满足AVL的特征
  3. 修复后,树的整体是不是不变

3、右右失衡和右左失衡和前面的刚好相反,这里只介绍一下它怎么旋转,具体的证明和前面的类似

​ 右右失衡:parent 左旋

​ 右左失衡: 先 cur 右旋,再 parent 左旋

总结插入过程:

1、按照普通搜索树的方式插入

2、插入之后,调整 parent.bf :插入到左边 bf --,插入右边 bf ++

​ bf 最后变为 3 类值

​ 0 :插入结束

​ -1/1:调整 bf 的过程向上蔓延(遇到 0 | -2 / 2 | 根节点 停止)

​ -2/2:进行修复,不会向上蔓延

3、针对失衡的情况进行修复

4、插入结束之后,是一颗 AVL 树

失衡分为四种情况: parent 是失衡的节点,cur 是 parent 的孩子(新节点所在子树的根)

左左失衡:parent右旋

左右失衡:先 cur 左旋,再 parent 右旋

右右失衡:parent 左旋

右左失衡: 先 cur 右旋,再 parent 左旋

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值