AVL树的定义:
<1> 每一个节点的子树都是一棵AVL树;
<2> 每一个节点的左右子树的高度差不超过1
以下讨论基于的前提:从图示的最顶层的节点开始平衡才被打破,它的子树都是平衡的。本身这个前提在代码实现时也是可以保证的,正常我们在插入一个树节点时都是从root开始层层遍历直到找到节点可插入的地方。由于节点的新插入可能会对树的平衡产生影响,所以在插入后需要对树进行重建。在寻找插入位置经过的路径上,每个节点都受到影响,其他节点均未受影响。所以可以采用递归的方式,先在"递"的过程中找到待插入的地方,再在"归"的过程中,查看平衡是否被打破,若被打破,则通过旋转来重建,归的过程就保证了先局部平衡再全局平衡。
关于AVL树的旋转的理解:
LL旋转: 节点3 开始平衡被打破,新插入的节点在节点3的左(L)子树的左(L)子树中。
从下图画出的结构关系,我们可以得到如下结论:
1、子树4的高度等于子树1、2的高度中的最大值;(由于节点3失去平衡)
2、子树1、子树2的高度大小顺序未知,但两者差的绝对值不超过1;(由讨论前提及AVL树定义)
3、子树3、子树4的高度肯定是相等的;
证明:假设不相等,则只可能子树3的高度大于子树4的高度,或者小于。如果大于,在本次新插入节点(新插入节点在1或其子树1中)前,节点2、3与子树3、4构成的树就已不平衡,假设不成立;如果小于,按节点3目前失去平衡来看,子树4的高度和节点1的左右子树的高度中的最大者应该是相等的,这样节点3的左子树就不平衡了,与讨论前提矛盾,假设不成立。所以不相等的假设不成立。
总结起来就是:height(子树3)= height(子树4)= max { height(子树1),height(子树2)} <公式1>
如图示,重新建立平衡的“旋转“,就是让节点1、2、3按大小顺序构树,再将子树1、2、3、4添加到节点1、3上。对于子树中的节点来说,他们的结构关系未发生重建,所以他们的平衡因子无需刷新,对于节点1、2、3,节点1的结构未发生变化,因子不变,节点2、3按公式1,均为BALANCED。
图示说明:圈代表树的节点,三角形代表子树,编号按值的大小进行排序。
LR旋转: 节点3 开始平衡被打破,新插入的节点在节点3的左(L)子树的右(R)子树中。
height(子树1)= height(子树4)= max { height(子树2),height(子树3)} <公式2> 证明过程类似,不再赘述。
如图示,重新建立平衡的“旋转“与前面一样,子树中的节点的平衡因子也无需刷新,对于节点1、2、3,节点1的因子依赖于旋转前节点2的因子,若BALANCED或LEFT,则节点1为BALANCED,若RIGHT,则LEFT;节点3的因子依赖于旋转前节点2的因子,若BALANCED或RIGHT,则节点1为BALANCED,若LEFT,则RIGHT;节点2按公式2,为BALANCED。
RR旋转: 节点1开始平衡被打破,新插入的节点在节点1的右(R)子树的右(R)子树中。
height(子树1)= height(子树2)= max { height(子树3),height(子树4)} <公式3> 证明过程类似,不再赘述。
如图示,重新建立平衡的“旋转“与前面一样,子树中的节点的平衡因子也无需刷新,对于节点1、2、3,节点1、2按公式3,为BALANCED;节点3结构未变,无需刷新。
RL旋转: 节点1 开始平衡被打破,新插入的节点在节点1的右(R)子树的左(L)子树中。
height(子树1)= height(子树4)= max { height(子树2),height(子树3)} <公式4> 证明过程类似,不再赘述。
如图示,重新建立平衡的“旋转“与前面一样,子树中的节点的平衡因子也无需刷新,对于节点1、2、3,节点1的因子依赖于旋转前节点2的因子,若BALANCED或RIGHT,则节点1为BALANCED,若LEFT,则RIGHT;节点3的因子依赖于旋转前节点2的因子,若BALANCED或LEFT,则节点1为BALANCED,若RIGHT,则LEFT;节点2按公式4,为BALANCED。