平衡二叉树是久闻大名了,但是因为其操作的繁琐以及存在更好的替代品所以没怎么接触(事实上是退队了以后就没怎么刷题
正巧这次期末考试就要考这个,那正好详细梳理一下知识:
平衡二叉树,其并没有字面上的那么平衡,其平衡程度能容忍任意节点的左子树高度与右子树高度的差之绝对值不超过1,为了理解方便,我们设定每个节点都有平衡因子,这个平衡因子由左子树高度减右子树高度而来,而且其绝对值不能超过1.
为什么说平衡二叉树没有那么平衡?因为它规定了一个节点的左子树不能和右子树相差过多,但是对于不同的节点之间的高度没有规定,也就是说,仍然是可能存在最深的叶节点和最浅的叶节点的高度差为2的情况的:
如图,我们可以轻松发现最右边的最浅叶节点和左边的最深叶节点之差为2,究其原因,是avl判断树高的时候只会算最高的树高,而其允许其子树内部的两个子树差为1
然后就可以想到,其实这么说来的话,我们可以将上图作为一个右子树附在一个父节点上,左边先接上同样的子树,然后每个叶节点添加左节点和右节点各一个,易证明该操作对于左子树完全合法,不会引起任何旋转。同样,对于我们刚创建的父节点来说,其左树仅比右树高1,也不会引起旋转。重复这个过程,则可以将最浅叶节点与最深叶节点的深度拉到无穷大。
故其实平衡二叉树并非如此平衡。
下面整理一下平衡二叉树的旋转:
a) Left Left Case
T1, T2, T3 and T4 are subtrees. z y / \ / y T4 Right Rotate (z) x z / \ - - - - - - - - -> / \ / \ x T3 T1 T2 T3 T4 / T1 T2b) Left Right Case
z z x / \ / \ / \ y T4 Left Rotate (y) x T4 Right Rotate(z) y z / \ - - - - - - - - -> / \ - - - - - - - -> / \ / T1 x y T3 T1 T2 T3 T4 / \ / T2 T3 T1 T2c) Right Right Case
z y / \ / \ T1 y Left Rotate(z) z x / \ - - - - - - - -> / \ / T2 x T1 T2 T3 T4 / T3 T4d) Right Left Case
z z x / \ / \ / \ T1 y Right Rotate (y) T1 x Left Rotate(z) z y / \ - - - - - - - - -> / \ - - - - - - - -> / \ / x T4 T2 y T1 T2 T3 T4 / \ / T2 T3 T3 T4
上面就是插入的旋转方法,要实现也不怎么简单,这四种,就笔者的猜测来看,是遍历了所有可能的违法状况。
在实际操作中,每插入一个节点,向上回溯直至终点。在这个过程中碰到任何平衡系数违法的情况,则对于这个违法节点进行旋转。
旋转操作应该按照这个就行了,有空的话会用pat的题库验证一下。
发现了一个有意思的性质,可以造福一下不想背旋转的考生:
a.查找树本身有这样的特性:假设a<b,那么存在两种安排的可能,a作为b的左儿子,或者b作为a的右儿子。
b.对于二叉查找树来说,其中序遍历即其增序排列;
拿上述的例子d来说,在遇到这样的情况时,我们想把它变成的样子肯定是
x
/ \
z y
(根据本来的大小关系,同时又要保证这三个构成的结果里每个字母节点的平衡系数为0)
但是这样的话,能从原来数据里搬过来的数据只有:
x
/ \
z y
/ \ / \
T1 ? ? T4
此时根据性质b,则存在增序:T1<z<T2<x<t3<y<T4
然后就可以开心的把原数据填上去,左边的问号为T2,右边的问号为T3.
这个就我看来,其本质是二叉搜索树对于大小关系可以允许不同的表示,故必然存在多种形式的表示。
时间: 2024-10-19 16:28:09