AVLTree深度剖析(单旋)

前言

二叉树搜索树是存在一定的缺陷问题的,当我们要插入的数据是有序,或者说接近于有序,,二叉搜索树及有可能退化为单支树,查找元素相当于在顺序表当中搜索元素,效率低下

AVLTree深度剖析(单旋)_第1张图片

---------------------------------------------------------------------------------------------------------------------------------

AVL树的概念

解决上述问题的方法是两位俄罗斯科学家发明的: 当向二叉搜索树当中插入新节点后,如果能保证每个节点的左右子树高度差的绝对值不超过1(超过对树当中的节点做调整),降低树的高度,从而减少平均搜索长度

一颗AVL树或者是空树,或者是具有以下性质的二叉搜索树:

1.它是左右子树都是AVL树

2.左右子树高度之差(简称平衡因子)的绝对值不超过(-1   /   0    /1)  平衡因子:右子树的高度-左子树的高度

AVLTree深度剖析(单旋)_第2张图片

 如果一颗二叉搜索树是高度平衡的,它就是AVL树,如果它有n个节点,其高度可保持在log_2(N),那么搜索的时间复杂度以2为底N的对数!!!

log以2为底n的对数是查找效率非常高的了,假设将我们全中国人口14亿人的数据保存在这样的一颗树当中,那么只需要查找31次,最多31次,高度次,是非常恐怖的!!!

-----------------------------------------------------------------------------------------------------------------------

实现AVL树

AVLTree深度剖析(单旋)_第3张图片

 为何我们在这里使用三叉链呢??

当我插入一个新节点之后,这棵树还是不是平衡树,我们就看高度差,不过呢平衡因子就是高度差的一个结果,在插入新节点之后我们得想办法更新平衡因子,更新的是祖先的平衡因子

AVLTree深度剖析(单旋)_第4张图片

 ----------------------------------------------------------------------------------------------------------------------

insert插入的实现

AVLTree深度剖析(单旋)_第5张图片

按照我们以前的搜索树的insert,到这一步也就结束了,但是我们这里插入之后,我们得控制平衡

有可能插入之后还是平衡的,也可能插入之后,不平衡了

AVLTree深度剖析(单旋)_第6张图片

我们在判断这颗树,或者子树是否平衡时,是通过平衡因子判断的,所以在判断是否平衡之前,得先更新平衡因子

更新平衡因子的规则:

1.新增在右,parent->_bf++    ,新增在左,parent->_bf--;

AVLTree深度剖析(单旋)_第7张图片

 2.更新后,parent->_bf  == 1或者-1  ,说明parent插入之前的平衡因子是0,说明左右子树高度相等,插入有一边高,parent的高度变了,继续往上更新

更新后,parent->_bf == 1   or  -1   ,  1代表右边高, -1代表左边高  ,这里要不要继续往上更新平衡因子的因素取决于,parent子树的高度是否变化,parent的平衡因子变为-1或者1,高度肯定的变了,为什么呢? 因为++  或者 -- 之后变为 -1 或者1  说明在不插入新节点之前是左右子树高度是一样的

我们在这里有没有可能parent的平衡因子是  2或者  -2   ,加加 减减之后变为 1或者-1 呢??肯定是不可能的,如果之前是2或者-2的画早就不平衡了,之前就应该做调整

AVLTree深度剖析(单旋)_第8张图片

3.更新后,parent->_bf ==0  ,说明parent插入之前的平衡因子  -1   或者  1  加加或者减减一下,说明左右子树一边高一边低,插入之后,两边一样高,说明插入填上了矮的那一边,parent所在的子树高度不变,不需要继续向上更新

AVLTree深度剖析(单旋)_第9张图片

 4.更新后,parent->_bf == 2或者-2  ,说明parent插入前的平衡因子是  1or  -1  ,说明在插入之前已经是平衡的临界值了,现在插入变成2或者-2  ,说明打破平衡,parent所在的子树,需要进行旋转处理

AVLTree深度剖析(单旋)_第10张图片

5.更新后,parent->_bf >2   or   parent->_bf < -2 ,不可能,如果存在则说明插入之前就不是AVL树,那需要去检查之前的操作问题

AVLTree深度剖析(单旋)_第11张图片

 此时这颗树,并没有发生旋转,但是快要发生旋转了,倾向于旋转了,好几个节点的平衡值都在临界值。

AVLTree深度剖析(单旋)_第12张图片

 -------------------------------------------------------------------------------------------------------------

我们现在写更新平衡因子的代码  -->   最坏的情况就是不断更新,更新到根节点,也可能中间就停止了

AVLTree深度剖析(单旋)_第13张图片

 接下来就是要处理我们的旋转问题了

AVLTree深度剖析(单旋)_第14张图片

在这里我们需要想办法去处理,无论是整颗树,还是子树

我们在这里处理的原则 :

1.旋转成平衡树

2.保持搜索树的规则

AVLTree深度剖析(单旋)_第15张图片

 对上面的情况网上有人做了归类

左单旋

AVLTree深度剖析(单旋)_第16张图片

 当h==2的时候,就已经有36种情况了

当h==3时,情况就更多了

如果我们要列举这里的情况,是无穷无尽的,但是对于上面情况当中的哪一种,我们的处理动作都是一样的

AVLTree深度剖析(单旋)_第17张图片

AVLTree深度剖析(单旋)_第18张图片

所以插入的时间复杂度是  高度次更新平衡因子+旋转的时间复杂度(O(1))

--------------------------------------------------------------------------------------------------------------------------

右单旋

AVLTree深度剖析(单旋)_第19张图片

a、b、c是h大于等于0的平衡树

AVLTree深度剖析(单旋)_第20张图片

 AVLTree深度剖析(单旋)_第21张图片

你可能感兴趣的:(数据结构高阶,数据结构)