算法,请不要这么经典 - 平衡二叉搜索树AVL
2015-05-06 14:42
375 查看
AVL 实现: https://code.csdn.net/hp_truth/data_structure_and_algorithm/tree/master/tree/AvlTree.h之前的一篇文章简单地介绍了二叉树的可视化,有了这个工具,可以更直观地对二叉搜索树进行理解。
二叉搜索树的查找比较简单,效率取决于树的左右子树是否平衡,对于平衡的二叉搜索树,查找的时间复杂度是O(n)。
而树是否平衡取决于主要是在插入和删除时是否保持平衡状态。
平衡的定义有很多中,比如AVL树和红黑树就各有不同的定义。本文主要讨论一下AVL树的插入和删除。
对于普通的二叉搜索树,插入可能会导致树退化成链表,比如将排序的数组元素插入到普通二叉搜索树,就会出现这样的情况,这种查找效率是线性的。
AVL树是通过限制每个节点的左右子树的高度差不能大于1来保证平衡性的。如果插入或删除后,某个节点的左右子树高度差大于1(等于2),
则会通过旋转来调整这棵树,使其重新达到平衡。
具体的实现代码可以参考我的git 代码。通过可视化输出,你可以自己来验证算法。
一些实现细节:
为了实现可视化功能的通用性,我们将这部分代码提取到一个工具类中TreeDumper。
同时我们定义了一个二叉树节点的基类模板BaseTreeNode<Comparable>,这样任何二叉树,只需继承这个基类就可以用TreeDumper来可视化了。
代码中bst.h是普通的二叉搜索树的模板实现,它是直接使用BaseTreeNode<Comparable>作为其节点。
bst2.h和bst.h很类似,它们的主要区别在一些成员函数的实现上,一个是使用指针的引用来实现,
而另一个是使用指针的指针来实现。
AvlTree.h中的AvlTreeNode则是继承了BaseTreeNode<Comparable>, 增加了一个成员height。
在类AvlTree的一些成员函数中,需要用到指针的引用,而递归的时候,left/right是基类类型,这里需要进行一次强制类型转换。
插入的例子:
比如,对于[1 .. 12]这个有序数组,插入普通的二叉搜索树会变成一个链表了:
而插入到AVL, 则是平衡的:
删除的例子:
比如,对于[6, 2, 8, 1, 3, 7, 4], 插入到AVL中后是:
删除6这个节点后变成:
相关文章推荐
- 算法,请不要这么经典 - 二叉树的可视化
- 【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C++)
- 【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C++)
- 【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C++)
- 【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C语言)
- 经典算法-对输入文件的格式化处理
- 图算法领域10大经典算法
- 数据挖掘十大经典算法(5) EM
- C语言经典算法(五)——求位设置的两种方法
- 经典算法题2:递归和字典序的全排列算法
- 经典基础算法之BST详解(系列二)(转)
- 图像匹配之:经典sift算法(二)
- 备战蓝桥杯——算法经典趣题(渔夫捕鱼)递归,递推,循坏算法
- Java经典算法汇总之顺序查找(Sequential Search)
- java经典算法四十题
- [转]数据挖掘十大经典算法
- 【LeetCode-面试算法经典-Java实现】【088-Merge Sorted Array(合并排序数组)】
- 经典算法(1)——8皇后问题求解(回溯法)
- java经典算法四十题
- DP DAG 9-3硬币问题(算法竞赛入门经典p162)