树·AVL树/平衡二叉树
1、AVL树
带有平衡条件的二叉查找树,所以它必须满足条件:
1 是一棵二叉查找树
2 满足平衡条件
1.1 平衡条件:
1)严格的平衡条件:每个节点都必须有相同高度的左子树和右子树(过于严格而不被使用)。
2)AVL树的平衡条件:每个节点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1)
1.2 特点:
严格的高度平衡,使得AVL树在查找时耗费时间更少。它理论上的时间复杂度为O(logN)。
虽然二叉查找树的平均时间也为O(logN),但是二叉查找树并不平衡,它的最坏情况是所有的子节点都只含有左子树,或者都只含有右子树,这种情况下,它的查找耗费的时间为O(N)。而平衡的AVL树可以避免这种极端情况。

2、AVL树的高度和最少节点个数S(h)的函数
2.1)假设一棵AVL树的最少节点数为S(h),h为树的高度。
2.2) 根据平衡条件,左右子树的高度最多差1,假设左子树的高度为h-1,右子树的高度为h-2。
2.3)根据2.2假设,节点总数=左子树节点数+右子树节点数+1。 ==》 S(h) = S(h-1) + S(h-2) +1
根据斐波拉契数可知,AVL树的节点个数与该数列密切相关。
高度为h的AVL树的最少节点总数:S(h) = S(h-1) + S(h-2) +1
3、维持AVL的平衡条件:旋转
根据AVL树的定义,它是带有平衡条件的查找树。平衡条件限制了它的每个节点的左右子树的高度差不能大于1,那么对于二叉树来说,插入操作是经常会出现的。当向一棵树插入一个节点时,难免会破坏AVL树的平衡条件,
比如:

在左图的AVL树中插入节点6,根据查找树的插入条件,节点6只能作为节点7度左子树。那么对于以8为父节点的子树来说,8的左子树的高度为2,右子树的高度为0,相差大于1。所以右图不再是AVL树。即失去了其存在的优势,不平衡的二叉查找树,时间复杂度增加。
所以我们需要在插入节点时,重新校验树的平衡条件,在必要时调整树的结构,使其保持为AVL树。这个简单的调整,我们称之为旋转!
我们把需要重新平衡的节点称为α(如上图的节点8),二叉树最多只有2个节点,而且不满足平衡条件,则α节点的左右子树高度差为2。容易看出,这种不平衡可能出现在下面4种情况。
1.对α的左儿子的左子树进行一次插入。(如上图,对节点8的左儿子7的左子树6进行一次插入)
2.对α的左儿子的右子树进行一次插入。
3.对α的右儿子的左子树进行一次插入。
4.对α的右儿子的右子树进行一次插入。
对于第1,4种情况,我们可以用单旋转进行平衡,对于2,3种情况,我们用双旋转进行平衡。
4、单旋转
很多时候,对于旋转还有另一种说法,左旋和右旋。顺便解释一下单旋转,双旋转,左旋,右旋的联系和区别。
1、第一种情况:对α的左儿子的左子树进行一次插入。

在原来的平衡AVL树上增加节点f,如上图!可见在增加了节点f之后,对应情况,对a节点的左儿子b的左子树c进行插入f。让a节点变得不再是平衡AVL树,这时候,我们对a树进行操作,使得它重新平衡。
操作的原理:我们把过深的树上移一层,把高层往下移一层。使之重新平衡。
如图:

讲解:在x树中,开始是平衡的,在左子树进行插入之后不再,x树不再平衡。为了使得x树平衡,我们采用的是右旋方法,旋转不平衡的子树,使得重新平衡。此处采用右旋一次,叫做单旋转。
2、第二种情况:对α的右儿子的右子树进行一次插入。
这种情况跟第一种一个样子。如图:对一棵平衡二叉树插入5,6两个节点。


5、双旋转
顾名思义:双旋转要用到左旋和右旋的组合,或者单方向2次旋转。
3、第三种情况:对α的右儿子的左子树进行一次插入。
如图:简单双旋转

讲解:在插入节点15之后,Z树变得不再平衡,这时,我们采用左旋或者右旋都明显的不能让树重新平衡,所以结合起来使用。我们的目的,是使得右子树降低一层高度。如果我们能使用左旋或者右旋即可达到目的,但是现在的样子明显不行,所以第一次旋转的目标:使得树可以使用一次旋转而重新平衡。为了让节点7,15,16重新排列,我们假设存在虚拟节点C,帮助我们理解第一次右旋。而后再进行左旋。所以这是一次“右-左双旋转”!
4、第四种情况:对α的左儿子的右子树进行一次插入。
如图,在上述平衡树上插入节点:14;

6、Java描述单旋转和双旋转:
代码地址:
https://github.com/dhcao/dataStructuresAndAlgorithm/tree/master/src/chapterFour
单旋转:右旋
/**
* desc:看懂上面的图,再看代码:参看第一种。
* 假设:k2树不再平衡,在k2的左儿子k1的左子树进行插入,导致k2子树不再平衡。采用右旋转
* 右旋转:
* 1.用k2的左子树k1来代替k2的位置。(k2丢失左子树)
* 2.让k2成为k1的右子树。
* 3.k1的右子树,重新成为k2的左子树。
*
* @auther: dhcao
*/
private AvlNode<T> rotateWithLeftChild(AvlNode<T> k2) { AvlNode<T> k1 = k2.left; k2.left = k1.right;
k1.right = k2;
// height方法返回该子树的 高
k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
k1.height = Math.max(height(k1.left), k2.height) + 1;
return k1;
}
双旋转:右-左双旋
private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
k3.left = rotateWithLeftChild(k3.left);
return rotateWithLeftChild(k3);
}
树·AVL树/平衡二叉树的更多相关文章
- 04-树4. Root of AVL Tree-平衡查找树AVL树的实现
对于一棵普通的二叉查找树而言,在进行多次的插入或删除后,容易让树失去平衡,导致树的深度不是O(logN),而接近O(N),这样将大大减少对树的查找效率.一种解决办法就是要有一个称为平衡的附加的结构条件 ...
- 树 -- AVL树
前言 通过之前对二叉查找树的讨论,我们知道在给定节点数目的情况下,二叉树的高度越低,查找所用时间也就越短. 在讨论红黑树的时候,我们说过红黑树并非完全"平衡"的二叉树,只是近似&q ...
- 红黑树/B+树/AVL树
RB Tree 红黑树 :http://blog.csdn.net/very_2/article/details/5722682 Nginx的RBTree实现 :http://blog.csdn ...
- 数据结构--树--AVL树
详情查看:http://www.cnblogs.com/skywang12345/p/3577360.html
- 红黑树和AVL树的实现与比较-----算法导论
一.问题描述 实现3种树中的两种:红黑树,AVL树,Treap树 二.算法原理 (1)红黑树 红黑树是一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是red或black.红黑树满足以 ...
- 二叉树,AVL树和红黑树
为了接下来能更好的学习TreeMap和TreeSet,讲解一下二叉树,AVL树和红黑树. 1. 二叉查找树 2. AVL树 2.1. 树旋转 2.1.1. 左旋和右旋 2.1.2. 左左,右右,左右, ...
- AVL树,红黑树,B-B+树,Trie树原理和应用
前言:本文章来源于我在知乎上回答的一个问题 AVL树,红黑树,B树,B+树,Trie树都分别应用在哪些现实场景中? 看完后您可能会了解到这些数据结构大致的原理及为什么用在这些场景,文章并不涉及具体操作 ...
- AVL树的介绍和实现
一.AVL树 AVL树是一种自平衡二叉查找树,因此在了解AVL树之前先介绍一下平衡二叉树.所谓平衡二叉树即该树中的任一个节点的左子树和右子树高度差不会超过1.如下图左是平衡二叉树,而右图则不是.节点4 ...
- 纸上谈兵:AVL树
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 二叉搜索树的深度与搜索效率 我们在树, 二叉树, 二叉搜索树中提到,一个有n个节点 ...
随机推荐
- 软件工程(FZU2015) 赛季得分榜,第一回合
SE_FZU目录:1 2 3 4 5 6 7 8 9 10 11 12 13 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分: 团队项目分=团队得分+个人贡献分 个人贡献分: 个人 ...
- 7 Servlet 会话技术
1 什么是会话 用户开一个浏览器访问某个网站,点击多个链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为会话,与打电话类似.会话过程要解决一些问题, 每个用户在使用浏览器与服务器进行会话时 ...
- Python【第四篇】函数、内置函数、递归、装饰器、生成器和迭代器
一.函数 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 1.定义 def 函数名(参数): ...
- bzoj4170 极光
题目链接 题面 题意 把每个位置的点都看成是一个二维坐标系中的点.比如第\(i\)个点就是\((i,a[i])\). 有两种操作 询问:然后每次询问的就是与当前点坐标的曼哈顿距离小于等于\(k\)的点 ...
- 洛谷P3369 普通平衡树
刚学平衡树,分别用了Splay和fhq-treap交了一遍. 这是Splay的板子,貌似比较短? Splay #include <iostream> #include <cstdio ...
- CNN:Channel与Core的高H、宽W的权值理解
转自: 知乎问题[能否对卷积神经网络工作原理做一个直观的解释?https://www.zhihu.com/question/39022858]中YJango 的回答; 因总是忘记回答地址,方便以后查阅 ...
- 柳叶刀重磅出击!全外显子测序在胎儿结构异常的评估Whole-exome sequencing in the evaluation of fetal structural anomalies: a prospective cohort study
柳叶刀发表的文献解读:Whole-exome sequencing in the evaluation of fetal structural anomalies: a prospective coh ...
- 一篇文章了解云安全领域的新宠CCSK
这是一个人人谈"云"."大数据"的时代,作为一个IT民工,如果与同行间聊天时,不谈及这方面的内容,有人可能会觉得你落伍了,跟不上这个时代了.随云计算.云存储之后 ...
- Ajax与JSON共同使用的小实例
实现的效果: 点击“点击”按钮,可以通过Ajax从服务器调过来相应的文档文件,而不需重新加载页面. 通过json可以将调过来的文档(String)转换为相应的json对象,从而对文档中数据进行操作. ...
- Kubernetes之Pod 控制器
定义Pod的常用资源 pods.spec.containers - name <string> #containers 的名字 image <string> ...