平衡二叉搜索树是二叉搜索树的升级版本。它拥有二叉搜索树的所有特性,同时它对子树的高度也进行了一定的限制。所以平衡二叉搜索树不会退化成链表的形式,而是维持了一个比较平衡的二叉树状态。
特点
在二叉搜索树的特点的基础上,平衡二叉树还要求对于任意节点X,X的左、右子树的深度相差最大不能超过1。如果某种操作(一般是插入和删除操作)破坏了这种平衡性,就要对树中不平衡的结点进行“旋转”来修复平衡性。
AvlTree
本平衡二叉搜索树的实现和之前的二叉搜索树实现很类似,都是包含了自定义的比较器。它们实现的不同点主要体现在平衡二叉搜索树的插入和删除操作要相对复杂一点,因为在元素插入或删除后,如果树的平衡性被破坏了还要进行平衡性的修复。
因为实现中需要频繁的计算左子树和右子树的高度差,所以我们在树中的节点里维护了一个表示当前结点的高度的变量。
成员变量
- private AvlNode
root : 平衡二叉搜索树。 - private Comparator
cmp : 比较器。
构造器
|
|
函数
- isEmpty() :判断树是否为空树
- clearTree() :重置树为空树
- findMin() :查询树中最小值,还包含一个重载的内部方法的实现。
- findMax() :查询树中最大值,还包含一个重载的内部方法的实现。
- print() : 前序遍历的按递增顺序输出树的元素。
- innerComparaTo() :内部比较器实现。
- contains() :二分查找查询树中是否包含元素X。
以上这些方法都是和二叉搜索树的类似或完全相同的,可以参考那边的实现,这里不再赘述了。传送门 ——> 二叉搜索树的实现
因为节点中维护了保存节点高度的变量,所以只要直接返回根节点的高度即可。
|
|
前序遍历
方法检验是否为平衡二叉搜索树。
|
|
insert()
:插入元素,主要在内部方法中递归实现。插入元素后,要判断左子树和右子树的高度差是否符合要求(不大于1),否则就要进行旋转操作。并且只有x位置到根节点的路径上涉及的节点可能会被改变。(x为插入元素的位置) 其中插入导致不平衡的情况只要有四种:(假设Q是需要重新平衡的节点)
- 在Q左儿子的左子树插入元素;
- 在Q左儿子的右子树插入元素;
- 在Q右儿子的左子树插入元素;
- 在Q右儿子的右子树插入元素.
其中1,4是对称的情况,只需要单旋转就可以处理;2,3是对称的情况,需要双旋转来处理.
|
|
这个算法不保证对的!这个算法不保证对的!这个算法不保证对的!重要的事情说三遍,= =。因为是仿造insert方法蒙出来的。(说蒙出来是因为经过若干组测试发现结果好像是对的,所以才放上来。)希望有大神帮看看本算法是不是可行,要是能指出错误并修正就更好了。= =。万分感谢。
|
|
单旋转
|
|
双旋转
|
|
内部类
|
|
源代码
|
|
测试代码
这里的测试主要是测试insert和remove方法执行之后,树是否还是平衡二叉树。
|
|
参考资料
- 《数据结构与算法分析-java语言描述 第2版》Mark Allen Weiss. 机械工业出版社.