平衡二叉搜索树
在二叉搜索树中,已经知道search、insert和remove等主要接口的运行时间均正比于树的高度。但是在最坏的情况下,二叉搜索树可能退化成列表,此时查找的效率会降至O(n)。因此,通常通过控制树高,来控制最坏情况下的时间复杂度。
对于节点数目固定的BST,越是平衡,最坏情况下的查找速度越快,如下图所示:
为了理解平衡二叉树,我们首先要理解几个主要概念,理想平衡与适度平衡以及如何进行等价变换让树更为平衡。
理想平衡与适度平衡
节点数目固定时,兄弟子树高度越接近(平衡),全树的高度也将倾向于更低。包含n个节点的二叉树,高度不可能小于log2(n)(向上取整),当树的高度刚好为log2(n)时,称作理想二叉树。例如完全二叉树和满二叉树。
但是大多数情况下,树不能满足完全二叉树的条件,因此要放宽平衡的标准。在渐进意义下,放松标准后的平衡性称为适度平衡(渐进的不超过O(logn))。 我们称可以保持适度平衡的BST称为平衡二叉树(BBST),例如AVL树、红黑树等。等价变换
若两颗二叉搜索树的中序遍历序列是相同,则称他们是相互等价的,反之亦然。例如:
总结出来,等价BST的特性即是:
上下可变:联系关系不尽相同,承袭关系可能颠倒。左右不乱:中序遍历完全一致。旋转调整
实际上任何一组等价BST的相互转换,都可以认为是一系列的基本操作串接而成的。最基本的修复手段就是通过围绕节点的旋转,实现等价前提下的的局部拓扑调整。
1、zig:顺时针旋转
2、zag:逆时针旋转
平衡二叉搜索树的适度平衡性,都是通过对树中每一局部增加某种限制条件来保证的。例如:AVL树中,兄弟节点高度相差不过1。除了适度平衡性,还有以下局部性:
1、经过单次动态修改操作之后,至多只有O(log(n))处局部不在满足限制条件。
2、在O(log(n))时间内,使这O(log(n))处局部(以至全树)重新满足限制条件。
意味着,刚刚失去平衡的二叉搜索树,可以通过(一系列zig或zag,只在局部操作可以在常数时间内完成)变换,转换成一颗等价的平衡二叉搜索树。AVL——BBST
首先给出所用的一些宏定义
#define Balanced(x) ( stature( (x).lc ) == stature( (x).rc ) ) //理想平衡条件
#define BalFac(x) ( stature( (x).lc ) - stature( (x).rc ) ) //平衡因子
#define AvlBalanced(x) ( ( -2 < BalFac(x) ) && ( BalFac(x) < 2 ) ) //AVL平衡条件
#define stature(p)((p)?(p)->height:-1)
/******************************************************************************************
* 在左、右孩子中取更高者
* 在AVL平衡调整前,借此确定重构方案
****************************************