概念
二叉搜索树概念:https://blog.csdn.net/weixin_43796685/article/details/104345502
AVL树代码:
https://github.com/DHaoYu/C-Cplusplus/tree/master/C%2B%2B/%E4%BA%8C%E5%8F%89%E6%A0%91/%E4%BA%8C%E5%8F%89%E6%A0%91
由于二叉搜索树退化成单支树(单链表)之后,查找元素的时间复杂度就会变成O(N),在实际应用中, 显然会影响效率,所以,为了解决这一问题,在二叉搜索树中引进了平衡因子这一概念,在二叉搜索树不平衡的时候将其调整为平衡状态。
所以AVL树具有一下性质
- 首先是一颗二叉搜索树
- 他的左右子树都为AVL树
- 左右子树的高度差(平衡因子)的绝对值不超过1(<=1)
- 即可将其保证在:搜索的时间复杂度为O(logN)
平衡因子
在二叉平衡树的每个结点内部维护着一个整型的元素bf,称之为平衡因子。并且一般定义为:左侧高平衡因子为负值,右侧高,平衡因子为正值。
下图中,结点之上的值即为平衡因子的值。
插入结点之后,调整平衡因子的三种情况
首先,当插入结点之后,需要先把插入结点的parent结点进行调整,
- 新节点在parent的左侧,parent的bf进行减减操作。
- 新节点在parent的右侧,parent的bf进行加加操作。
在对parent的平衡因子进行调整完之后,parent的平衡因子分为三种情况。
情况一:parent的平衡因子为0, 这说明在插入之前为正负一,插入之后,变为0,可以保证整棵树是平衡的,直接跳出循环即可。
情况二:parent的平衡因子为正负一,这说明,插入结点之后,父亲结点的平衡性遭到了改变,为了使整个树为AVL树,则需要向上进行调整。(将父亲结点视为插入的结点,将祖父结点视为父亲结点,直到调整到根节点)
情况一和情况二还可以理解,下面看一下情况三
情况三:需要进行左旋、右旋、左右双旋、右左双旋
第三种情况是最复杂的一种情况,当插入结点之后,父亲结点平衡因子的值改为了正负二的情况。
上图所示即为第三种情况中的一种。需要对其进行旋转操作。
左旋
第一步:进行旋转
第二步:更改平衡因子的值
右旋
右旋和左旋的方式相同,第一步旋转,第二步更改平衡因子
上述两种方式,都为新节点插入在较高子树的同一侧(左子树较高,插入位置是左侧,右子树较高,插入位置是右侧)
左右双旋
该旋转主要针对于插入较高子树的异侧(左子树较高,插入较高左子树的右侧)
双旋的主要思想是,把在异侧的结点先调整为在同侧,这样就可以进行单旋。
右左双旋
主要思想依旧是调整为单旋时的场景,在使用单旋场景,进行更新。