AVL树(艾薇儿树)

接上章:二叉搜索树(Binary Search Tree).

通过二叉搜索树的学习,我们发现,二叉搜索树节点的添加和删除都是随机的,这里就会产生一种特殊情况,如下图所示:

1672235-54c81bafd914a42a.jpg
001.jpg

此种情况,是从小到达的添加各个节点,此时二叉搜索树已经退化为链表了。或者删除节点,也可能会导致搜查搜索树退化成链表。那么,如何防止二叉搜索树退化成链表呢?
因为二叉搜索树的复杂度在O(logn),所以在添加、删除二叉搜索树节点的时候复杂度一直维持在O(logn)即可。这里有一个平衡二叉搜索树的概念。

平衡:当节点数量固定时,左右子树的高度越接近,这棵二叉树就越平衡(高度越低)。

1672235-b623dc145df9efc3.jpg
002.jpg

西方有一句民谣是这样说的:“丢失一个钉子,坏了一只蹄铁;坏了一只蹄铁,折了一匹战马;折了一匹战马,上了一位骑士;上了一位骑士,输了一场战斗;输了一场战斗,亡了一个帝国。”所以,所谓平衡二叉树,其实就是在二叉树添加删除的过程中保证它的平衡性,一旦发自按有不平衡的情况,马上处理恢复平衡,这样就不会造成不可收拾的情况出现了。
也就是说,在添加、删除操作之后,想办法让二叉搜索树恢复平衡(减小输的高度)即可。
经典常见的平衡二叉搜索树也就是我们今天所说的AVL树。

一、【AVL树】性质:

◼ 平衡因子(Balance Factor):某结点的左右子树的高度差
◼ AVL树的特点
◼ 每个节点的平衡因子只可能是 1、0、-1(绝对值 ≤ 1,如果超过 1,称之为“失衡”)
◼每个节点的左右子树高度差不超过 1
◼搜索、添加、删除的时间复杂度是 O(logn)
添加、删除操作均会导致AVL树失衡

例:我们先来看一个平衡二叉树构建的例子。假设我们有如下一个数组a[10]= {3,2,1,4,5,6,7,10,9,8},需要构建二叉搜索树。在没有学习AVL树之前,根据二叉搜索树的特性,我们通常会将它构建成如图003-图1所示。

1672235-051ddde90de53d77.jpg
003.jpg

虽然它完全符合二叉搜索树的性质,但是对于这样高度达到8的二叉搜索树来首,查找是非常不利的。我们更期望能够构建成如图003-图2所示的样子,高度为4的二叉搜索树才可以提高查找的效率。那么现在我们来看一下如何构建出如图003-图2所示的树结构。

二、【AVL树】节点的增加和删除
1.节点添加步骤:

我们根据数组a[10]= {3,2,1,4,5,6,7,10,9,8},来一个个添加元素.

1. 前两位【3】和【2】我们都很正常的构建,到了第三个数字节点【1】的时候,发现此时根节点【3】的平衡因子变成了2,此时整棵树都成了最小的不平衡子树,因此需要调整。所以需要将整个树进行右旋转(顺时针旋转),此时节点【2】成了根节点,【3】成为【2】的右孩子,这样三个节点的平衡因子值均为0,非常的平衡,完成了平衡二叉树的调整。如下图所示:

1672235-9a1cc2fa674cad6b.jpg
004.jpg

2. 接着添加节点【4】,平衡因子此时没发生改变,如图005所示

1672235-704fecc659581235.jpg
005.jpg

3. 接着添加节点【5】,节点【3】的平衡因子值为-2,说明要旋转了。所以我们对这棵最小平衡子树进行左旋(逆时针旋转),如图006所示,此时整个树又达到了平衡。

1672235-b704fc28f0e99d2e.jpg
006.jpg

4. 继续添加节点【6】,发现根节点【2】的平衡因子变成了-2,如图007-图1所示。所以需要对根节点进行左旋转,注意此时本来根节点【3】是【4】的左孩子,由于旋转后需要满足二叉搜索树的性质,所以它成了节点【2】的右孩子。如图007-图3所示。

1672235-e65afc3dfe9fae40.jpg
007.jpg

5. 继续添加节点【7】 ,发现节点【5】的平衡因子变成了-2,所以同样的左旋转,使得整棵树达到平衡,如图008所示。

1672235-c4ddf0dc14554e4f.jpg
008.jpg

6. 继续添加节点【10】,结构无变化,如图009所示。

1672235-faab9afa6fe01861.jpg
009.jpg

7. 继续再添加节点【9】,此时节点【7】的平衡因子变成了-2,因为节点【9】是父节点【10】的左孩子,由于旋转后需要满足二叉搜索树的性质,所以这里需要进行两次旋转。
7.1 先对节点【9】和节点【10】进行右旋转,使得节点10成了9的右子树。
7.2 再以节点【7】为最小不平衡子树进行左旋转
旋转过程如图010所示:

1672235-519d7ae75225b8d1.jpg
010.jpg

中间转换过程放大图如下:
1672235-bac9eaeb770e174f.jpg
010-1.jpg

8. 最后添加节点【8】,情况与刚刚类似,需要进行两次旋转。
8.1 先以节点【9】为根节点,进行右旋
8.2 再以节点【6】为根节点,进行左旋

右旋转过程如图011所示:

1672235-04934829fa780a7c.jpg
011.jpg

右旋中间转换过程放大图:

1672235-f82536d7e12dfdc4.jpg
011-1.jpg

左旋转过程如图012所示:
1672235-e06c9074308207fd.jpg
012.jpg

左旋中间转换过程放大图:
1672235-3ac0e6bff5aa3e47.jpg
012-4.jpg

通过这个例子,我们可以总结出来,AVL树的旋转一共分为四种情况,分别是LL,RR,LR,RL。

这里我们定义一个二叉搜索树P
左子节点定义为L,
右子节点定义为R,
三角形代表子树,
N定义为新增节点

情况一:LL-右旋转(单旋)
◼ ① L.right = P.left;
◼ ② P = L.right
◼ ③ 让L成为这棵树的根节点
◼ ④ 整棵树达到了平衡
注意:(1).LR、L、P的parent;(2).先后更新P、L的高度。

1672235-7c0f0e4f87c8cfd6.jpg
LL.jpg

情况二:RR-左旋转(单旋)
◼ ① R.left = P.right;
◼ ② P = R.left
◼ ③ 让R成为这棵树的根节点
◼ ④ 整棵树达到了平衡
注意:(1).RL、R、P的parent;(2).先后更新P、L的高度。

1672235-d2d33700650f5cec.jpg
RR.jpg

情况三:LR-左右旋转(双旋)
◼ 只需要先旋转,使平衡因子BF值符号统一,然后再进行旋转。

1672235-ed9a0e95dd5d3404.jpg
LR.jpg

情况四:RL-右左旋转(双旋)
◼ 只需要先旋转,使平衡因子BF值符号统一,然后再进行旋转。

1672235-7a9d555477e0aaf8.jpg
RL.jpg

2.节点删除步骤:

添加节点可能导致AVL树失衡,那么节点也可能导致AVL树失衡。如下图所示,删除节点后平衡因子如下:

1672235-4665f191422f341b.JPG
删除节点.JPG

◼ 删除子树中的 16
◼ 可能导致了父节点15失衡了。这里属于LL的情况,所以进行左旋转,调整后如下所示:

1672235-569b95fe3f9f45db.png
旋转.png

好了,AVL树的学习先暂且到这里,后序如果有更深入的了解,继续补充学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值