笔记-AVL树
来源:互联网 发布:debian和ubuntu哪个好 编辑:程序博客网 时间:2024/05/16 12:05
AVL树是带有平衡条件的二叉查找树。
为什么需要平衡捏?
之前看的二叉查找树,在进行大量插入与删除操作时,会出现左子树越来越深(可以理解为元素节点越来越多,比右子树多很多)的情况,因为删除时经常把右子树中的节点拿出来替代删除的节点,这样在对树操作时会降低效率。因为操作时大多会往左检索,而需要检索的节点会越来越多。
所以,如果使树维持在左右两部分大致差不多的情况,在差不多的数据量下,效率明显更高。
一棵AVL树,其每个节点的左右子树的高度最多相差1。
如果一个节点的左右子树的高度相差超过1,我现在称它为不平衡。
为了保证每个节点的左右子树的高度最多相差1。
首先对删除操作实行懒惰删除。即当要删除一个节点上,只是对其进行标记,并不真的将其删除,其任然留在树中。这特别是在有重复项时很常用,因为此时记录出现频率数的域可以减1。如果树中的实际节点数和“被删除”的节点数相同,那么树的深度预计只上升一个小的常数。如果被删除的项是重新插入的,那么分配一个新单元的开销就避免了。
对插入操作,我们需要更新通向根节点路径上那些节点的所有平衡信息,判断是否让树平衡被打破,即树中某一节点的左右子树的高度最多相差超过1。如果平衡被破坏,则需要修正,称其为旋转。
简单来说,会破坏平衡的操作(插入)有四种:
1左左--左;2左左--右;3右右--左;4右右--右。1和4镜像对称,2和3镜像对称。
1和4需要一次单旋转,2和3则需要复杂些的双旋转。
单旋转
对于什么时候单旋转,即1和4的情况,我觉得可以这样理解:
即插入的打破平衡的新元素(A),并不在被打破平衡的节点(B)(该节点在插入新元素后左右子树的高度最相差2>1),与B到A的路路径的儿子节点(C)之间。
1左(B)左(C)--左(A):A比B和C都小。
4右(B)右(C)--右(A):A比B和C都大。
(2和3的情况就可以简单的理解为A在B和C之间,双旋转)
(备注:C是B的儿子节点,A是C的子节点,但A不一定是C的儿子节点,A可能距离B很远,但是它的插入却会使B不平衡)
此时进行单旋转。单旋转怎么旋转捏?
谁被打破,旋转谁,即改变谁。可以很明显看出应该旋转B,即用B的儿子C替换B,
对1左(B)左(C)--左(A)的情况就是 :C原本是B的左儿子,让其替换到B的位置,C成为父节点,B成为其右儿子。
对4右(B)右(C)--右(A))的情况就是:C原本是B的右儿子,让其替换到B的位置,C成为父节点,B成为其左儿子。
此时树就又平衡了。(//没有图,真是不知道怎么解释,如果有图,应该一目了然)
双旋转
双旋转实际就是两次单旋转
对于2和3的情况,单旋转不能使树平衡。(可以画图试试)。所以我们先旋转一次,使其成为1和4的情况。
此时被改变的任然是B,因为它不平衡了嘛。而此时不是用B的儿子C来代替B,而是用C的儿子节点来替换B。
若A就是C的儿子节点,则直接用A代替B,若A不是C的儿子节点,则再引入C的一个儿子节点D来进行讨论。
若A是C的左子节点(即A在C的左子树上),则D为C的左儿子节点。同理,若A是C的右子节点(即A在C的右子树上),则D为C的右儿子节点。
此时用D来代替B。
再让树满足二叉查找树的基本条件后,树就右平衡了。
本篇不敢标记为转载,因为不是照打书上的类容,上面均是个人理解。勿盲信!
伸展树
- AVL树初学笔记
- 笔记-AVL树
- 学习笔记 AVL树
- 数据结构学习笔记--AVL树
- AVL树学习笔记&模板
- AVL树的学习笔记
- AVL树(二叉平衡树)笔记
- 平衡二叉树AVL的笔记
- 平衡二叉树AVL的笔记
- 【学习笔记】AVL树的实现
- [学习笔记]AVL平衡二叉树
- AVL树笔记(二):maintain,delete
- 平衡二叉树(AVL)代码笔记
- avl树-《算法导论》学习笔记十三
- AVL树
- AVL树
- AVL树
- avl树
- poj1170(状态压缩dp)
- 电量统计之一:PowerProfile.java与power_profile.xml
- 结构体日期计算
- POJ 1251.Jungle Roads【最小生成树】【4月15】
- EhCache 分布式下缓存对象的同步
- 笔记-AVL树
- Eclipse安装主题(Color Theme)
- 安卓手机震动效果
- JQuery绑定事件的四种方法
- 标准C++类std::string的内存共享和Copy-On-Write技术
- 智合福金:九大问题帮助你了解本周多哈会议!
- Unity3d大会
- Java高吞吐量系统设计优化建议
- HTML5第五次培训(jQuery)