平衡二叉树(AVL树)
平衡二叉树是一种二叉排序树,平衡二叉树的出现是为了解决二叉搜索树因为高度太高而查找效率下降的问题。
如:对于数组a[10]={3,2,1,4,5,6,7,10,9,8}.分别构建二叉搜索树和平衡二叉树。
如果要查找结点8,左边二叉搜索树搜索过程为:3->4->5->6->7->10->9->8,要查找8次。而平衡二叉树搜索过程为:4->7->9->8,只要搜索8次,可以看出当二叉搜索树高度变得很高之后搜索效率会下降很多。
1.平衡二叉树(AVL树)定义
平衡二叉树是一种二叉搜索(排序)树,其中每一个结点的左子树或右子树的高度差至多等于1.
平衡二叉树是一种高度平衡的二叉搜索(排序)树。 我们将二叉树结点的左子树高度减去右子树高度的值称为平衡因子BF, 那么平衡二叉树的所有结点的平衡因子只可能是-1,0,1。
例:判断下列树是否为平衡二叉树
距离插入节点最近的,且平衡因子的绝对值大于1的结点为根的子树,称为最小不平衡子树。
如:插入结点51后,距离它最近的平衡因子超过1的结点是58,所以从58开始以下的子树为最小不平衡子树。
2.平衡二叉树的实现原理
二叉平衡树构建的基本思想就是在构建二叉排序树的过程中,每当插入一个结点时,先检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡子树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各节点之间的连接关系,进行相应的旋转,使之成为新的平衡子树。
我们先来介绍一下树的旋转方便后续学习。
树的旋转是为了调平一棵二叉树,使得左右结点数目分布均匀。分为左旋和右旋。
例:数组a[10]={3,2,1,4,5,6,7,10,9,8}的平衡二叉树的构建过程如下:
- 插入结点3和结点2。
- 插入结点1之后,结点3的BF值变成了2(>0),因此对最小不平衡子树进行顺时针旋转,调整得到下右图。
- 插入结点4。
- 插入结点5之后,结点3的BF值变成了-2(<0),因此对最小不平衡子树进行逆时针旋转,调整得到下右图。
- 插入结点6之后,结点2的BF值变成了-2(<0),因此对最小不平衡子树进行逆时针旋转,注意结点3本来是结点4的孩子,但是为了满足平衡二叉树的特性,因此变成结点2的孩子,调整得到下右图。
- 插入结点7之后,结点5的BF值变成了-2(<0),因此对最小不平衡子树进行逆时针旋转,调整得到下右图。
- 插入结点10。
- 插入结点9后,结点5的BF值变成了-2(<0),但这时对最小不平衡子树不管怎么旋转都不符合二叉排序树的特性。这是因为,结点7的BF值为-2,结点10的值为1,符号不统一。那么我们就先将其变成统一,先对结点9和结点10顺时针旋转得到下中图,再对最小不平衡子树进行逆时针旋转就可以了,调整得到下右图。
- 插入结点10之后,结点6的BF值变成了-2(<0),与上述类似,9结点的BF值为1,先对结点9为根节点进行右旋转,根据二叉排序树准则,8结点本来是7的子树,旋转过后变成了结点9的子树,如下中图。然后对最小不平衡子树进行逆时针旋转,调整得到下右图。
所谓平衡二叉树,就是在二叉搜索(排序)树创建过程中保证它的平衡性,一旦发现不平衡的情况就马上处理:
- BF值大于1就对最小不平衡子树顺时针旋转。
- BF值小于-1就对最小不平衡子树逆时针旋转。
- 最小不平衡子树BF值与它的子树的BF符号相反时,相对子树进行旋转调整符号与最小不平衡子树符号相同,然后再对最小不平衡子树进行旋转。