树(四)——AVL树和旋转操作原理
基本概念
高度:根到其叶子的的最长路径距离,空子树的高度被规定为-1。
AVL树是带有平衡条件的二叉查询树。通常来说,一棵AVL树的每个节点的左子树和右子树的高度最多相差1。在高度为h的AVL树中,节点数最少是S(h),S(h)可由递推关系得出:S(h)=S(h-1)+S(h-2)+1;同时S(0)=1;S(1)=2。
当进行插入操作的时候,需要更新通向根节点路径上的那些节点的所有平衡信息。而插入一个新节点有可能导致AVL树的平衡情况被破坏,需要通过旋转来修复。
旋转
可以发现一个节点,它的新平衡情况破坏了AVL条件,重新平衡这个节点将保证整个树重新满足AVL性质。
这个必须重新平衡的节点叫做α。它最多有两个儿子,所以一共有以下四种情况:
- 对α的左儿子的左子树进行一次插入
- 对α的左儿子的右子树进行一次插入
- 对α的右儿子的左子树进行一次插入
- 对α的右儿子的右子树进行一次插入
情况1和4是相同的情况,通过单旋转可以恢复平衡条件。情况2和3是相同的情况,可以通过双旋转来恢复平衡条件。
单旋转
出现1和4的情形可以使用单旋转:
如图中需要在子树1中添加节点,这会破坏4节点的平衡情况。首先,这是由于子树1的高度增加导致的平衡条件破坏,也就是子树1增加一个节点后会增加1的高度。而子树5此时和节点2的高度相差1,在子树1增加一个节点后高度差变成2。由此可见需要降低子树1的一个高度,作为代价增加子树5的一个高度,增加子树5的高度不会影响整棵树的平衡性,因为它本来就比节点2的高度少1,加一个高度的话高度差也才变成0。于是进行下图的变换:即将子树3变成4节点的左子树,2节点变成新的根节点,4节点变成2节点右子树。
这将会使子树1的高度减1,子树3的高度不变,子树5的高度加1.整理后可得:
双旋转
在2和3的情况中,插入操作发生在子树3中,经过上述的分析,单旋转无法改变子树3的高度,因此2和3的情况无法通过使用单旋转来达到平衡。在此描述双旋转的操作:
我们假设要插入的右子树有两个儿子3和5(没有儿子也没有任何关系,认为3和5是null就行),将子树3变成节点6的左子树,子树5变成节点2的右子树,2和6分别变成节点4的左右儿子。也就是4变成了新的根节点,如下:
显而易见,子树3和5降低了一个高度,子树1没有变化,子树7增加了一个高度。