首先介绍一下AVL旋转树:AVL树也是一棵二叉搜索树,AVL树存在的原因是避免二叉搜索树因为左右子树高度相差过大使得查找花费过多时间。
下面就来介绍一下AVL树的实现,这里重点介绍AVL中的Insert接口,因为这个结构就包含了AVL的所有精华。
1、插入节点
要插入一个节点就必须先找到节点要插入的位置,因为AVL树同时也是一棵平衡树,所以用循环或递归很容易就可以找到。插入时要注意是插在左子树还是右子树。
2、更新平衡因子
(1)首先判断一下是插在左子树还是插在右子树:如果插入在左子树,那么父节点的平衡因子少1;否则就加1;
(2)其次要循环向上判断,知道到达根节点。这里分为三种情况:a、如果父节点的平衡因子为0,说明平衡因子是由-1或1转变而来,树的高度没有变化,就不必往上判断了。b、如果父节点的平衡因子为-1或1,说明平衡因子原来是0,树的高度发生了变化,需要进一步往上判断,看需要对树做出什么样的调整。3、如果父节点的的平衡因子为-2或2,则进行选转。
3、旋转
(1)左单旋(右单旋):当父节点的平衡因子为2,父节点的右节点平衡因子为1则进行左旋
如图所示,d或者3是新增节点
我们将父节点定义为parent,父节点的右节点定义为subR,subR的左节点定义为subRL。左旋使节点subR作为树的父节点,parent作为subR的左节点,从而降低树的高度。
a、将subRL链到parent的右子树上
b、将parent链到subR的左子树上
c、连接父节点(需要判断有无父节点)
(2)左右双旋(右左双旋):当父节点的平衡因子为-2,父节点的右节点平衡因子为1则进行左右双旋
如图所示,d或3为新增节点
a、先将以2为根节点的树进行左单旋
b、将以1为根节点的树进行右单旋
c、调整平衡因子(这里是个重点,因为有多种不同的情况)
在上图中,我们可能会发现其实双旋也挺简单的,其实不然。有些复杂的东西我们还没有考虑到。
重点在于调整平衡因子,其实在左单旋和右单旋的过程中,平衡因子就已经被调整过了(1,2,3的平衡因子都被调为0),但是单单这样的调整是有问题的。
(i)如果插入的是节点d,而节点c不存在。
由图可知,节点2的平衡因子并不为0
(ii)如果插入的是节点c,而节点d不存在。
由图可知,节点1的平衡因子并不为0
(iii)如果3的平衡因子为0
那么就是正常的情况
根据以上的分析可以得出:
节点3的平衡因子无论如何都为0;
调节1,2平衡因子的时候要判断一下节点3的平衡因子(当然是节点3没有被调整时候的平衡因子)