AVL树的理解及自写AVL树
AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。
节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反)。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。
AVL树的基本操作一般涉及运作同在不平衡的二叉查找树所运作的同样的算法。但是要进行预先或随后做一次或多次所谓的"AVL旋转"。
以上内容转自维基百科AVL树
从图中可以比较形象的看出所谓左旋右旋的旋转支点是三个主节点中大小居中的那个节点,左旋就是左边的节点降下来,右旋就是右边的节点降下来,都成为中间节点的子树。
左右双旋分解就是先将左侧节点降为左子树,右边节点将为右子树。当然中间有合并子树的过程,这里没有细说。
高度为h的AVL树,节点数N最多; 最少 ( 其中 )N是h的斐波那契数列。
//定义节点
class AvlNode{
int val;
AvlNode left;
AvlNode right;
int height;
public AvlNode(int val,AvlNode left,AvlNode right){
this.val=val;
this.left=left;
this.right=right;
this.height=0;
}
public AvlNode(int val){
this(val,null,null);
}
}
public class AVLTree {
private static final int COUNT=1;
//判断高度
private static int height(AvlNode t) {
// TODO Auto-generated method stub
return t==null?-1:t.height;
}
//节点的插入
public static AvlNode insert(Integer val,AvlNode t){ if(t==null){
return new AvlNode(val);
}
int result=val.compareTo(t.val);
if(result<0){
t.left=insert(val, t.left);
}
else if(result>0){
t.right=insert(val, t.right);
}else{
;
}
//其余按照普通的二叉查找树来写,最后加一个平衡方法
return balance(t);
}
//删除方法,选择了一种比较简单的,在删除之后重新调整树
public static AvlNode remove(Integer x,AvlNode t){
if(t==null){
return null;
}
int result=x.compareTo(t.val);
if(result<0){
t.left=remove(x, t.left);
}else if(result>0){
t.right=remove(x,t.right);
}
else if(t.left!=null&&t.right!=null){
t.val=findMin(t.right).val;
t.right=remove(t.val,t.right);
}else{
t=(t.left!=null)?t.left:t.right;
}
return balance(t);
} private static AvlNode findMin(AvlNode t) {
if(t==null){
return null;
}else if(t.left==null){
return t;
}
return findMin(t.left);
}
//平衡方法
private static AvlNode balance(AvlNode t) {
// TODO Auto-generated method stub
//判断是哪种情况
//如果是左左情况或者是左右情况
if(height(t.left)-height(t.right)>COUNT){
if(height(t.left.left)-height(t.right.right)>COUNT){
//左左情况进行右旋
t=rightSpin(t);
}else{
//右左情况先左旋后右旋
t=leftrightSpin(t);
} }
//如果是右右情况或者是右左情况
else if(height(t.right)-height(t.left)>COUNT){
if(height(t.right.right)-height(t.right.left)>COUNT){
//右右情况进行左旋
t=leftSpin(t);
}else{
//右左情况先右旋再左旋
t=rightleftSpin(t);
}
}
return null;
}
private static AvlNode rightleftSpin(AvlNode t) {
t.right=rightSpin(t.right);
return leftSpin(t);
}
private static AvlNode leftrightSpin(AvlNode t) {
t.left=leftSpin(t.left);
return rightSpin(t);
}
private static AvlNode leftSpin(AvlNode t) {
AvlNode t1=t.right;
t.right=t1.left;
t1.left=t;
t1.height=Math.max(height(t1.left), height(t1.right))+1;
t.height=Math.max(height(t.left),height(t.right));
return t1;
}
private static AvlNode rightSpin(AvlNode t) {
AvlNode t1=t.left;
t.left=t1.right;
t1.right=t;
t1.height=Math.max(height(t1.left), height(t1.right))+1;
t.height=Math.max(height(t.left),height(t.right));
return t1;
} }
AVL树的理解及自写AVL树的更多相关文章
- 手写AVL 树(下)
上一篇 手写AVL树上实现了AVL树的插入和查询 上代码: 头文件:AVL.h #include <iostream> template<typename T1,typename T ...
- 数据结构图解(递归,二分,AVL,红黑树,伸展树,哈希表,字典树,B树,B+树)
递归反转 二分查找 AVL树 AVL简单的理解,如图所示,底部节点为1,不断往上到根节点,数字不断累加. 观察每个节点数字,随意选个节点A,会发现A节点的左子树节点或右子树节点末尾,数到A节点距离之差 ...
- 常见基本数据结构——树,二叉树,二叉查找树,AVL树
常见数据结构——树 处理大量的数据时,链表的线性时间太慢了,不宜使用.在树的数据结构中,其大部分的运行时间平均为O(logN).并且通过对树结构的修改,我们能够保证它的最坏情形下上述的时间界. 树的定 ...
- 手写AVL平衡二叉搜索树
手写AVL平衡二叉搜索树 二叉搜索树的局限性 先说一下什么是二叉搜索树,二叉树每个节点只有两个节点,二叉搜索树的每个左子节点的值小于其父节点的值,每个右子节点的值大于其左子节点的值.如下图: 二叉搜索 ...
- 平衡二叉查找树(AVL)的理解与实现
AVL树的介绍 平衡二叉树,又称AVL(Adelson-Velskii和Landis)树,是带有平衡条件的二叉查找树.这个平衡条件必须要容易保持,而且它必须保证树的深度是 O(log N).一棵AVL ...
- [BinaryTree] AVL树、红黑树、B/B+树和Trie树的比较
转自:AVL树.红黑树.B/B+树和Trie树的比较 AVL树 最早的平衡二叉树之一.AVL是一种高度平衡的二叉树,所以通常的结果是,维护这种高度平衡所付出的代价比从中获得的效率收益还大,故而实际的应 ...
- Atitit 常见的树形结构 红黑树 二叉树 B树 B+树 Trie树 attilax理解与总结
Atitit 常见的树形结构 红黑树 二叉树 B树 B+树 Trie树 attilax理解与总结 1.1. 树形结构-- 一对多的关系1 1.2. 树的相关术语: 1 1.3. 常见的树形结构 ...
- 【面试普通人VS高手系列】b树和b+树的理解
数据结构与算法问题,困扰了无数的小伙伴. 很多小伙伴对数据结构与算法的认知有一个误区,认为工作中没有用到,为什么面试要问,问了能解决实际问题? 图灵奖获得者: Niklaus Wirth 说过: 程序 ...
- 瞎写的树dfs序
这里枚举了树的DFS序来解决树上问题的多个板子,自己最好多看看. ↓改↓ ↓求↓ 点 点 ————————>>>这个就算了 点 树 简单, BIT 点 链 重点! 树 树 简单, 线 ...
随机推荐
- js 浮点数相加 变成字符串 解决方案
var count = 0; count+=Number(parseFloat(value[i]['sla']).toFixed(2)); 数字相加的时候最好使用Number转换一下
- 集腋成裘-05-angularJS -初识angular
私以为angular的最大特点是:只关注数据 1.1 angular之:双向绑定 <!DOCTYPE html> <html ng-app=""> < ...
- svn_linux + apache 实现网页访问svn
CentOS7:搭建SVN + Apache 服务器实现网页访问 1. 安装httpd 安装httpd服务: $ sudo yum install httpd 检查httpd是否安装成功: $ htt ...
- PAT Basic 1065 单身狗
单身狗(25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue "单身狗"是中文对于单身人士的 ...
- 主流前端框架对比:Vue.js , React, Angular.js
个人认为Vue.js的文档最恳切.我认为结合文档和遇到问题Google答案的匹配度来讲:Vue.js > ReactJS > AngularJS > Angular 2 如何使用Vu ...
- 小改造gotty,使之适合接收经过一层加密的URL
当然,比起密码设置,这个安全性也不是特别高, 但比起直接传参数. 还是要专业一些的. 其实现思路分两种: 第一种是在gotty.js之内加入解url的函数. 第二种在是go源代码时,加入同等的解密函数 ...
- mysql的时间戳timestamp精确到小数点后六位
1.mysql的时间戳timestamp精确到小数点后六位. 公司业务使用到Greenplun数据库,根据查询的时间戳来不断的将每个时间段之间的数据,进行数据交换,但是今天发现,mysql的时间戳没有 ...
- springboot调用http方式
1.httpclient 2.okhttp 3.feign 安装Gradle包 compile 'org.springframework.cloud:spring-cloud-starter-open ...
- 铺放骨牌 uva11270
题解: 插头dp裸题 没什么好说的啊就是n个二进制位表示状态 相比原先就是用2n个二进制位表示状态 蓝书上后面几题插头dp都挺烦的啊... 代码:
- cf666 C. Codeword 组合数学
题解: 首先暴力很显然 f[i][j]表示到第i个位置,串匹配到j 这样每次是n^2的 我们假设每个位置匹配的第一个位置 然后从这个到上一个位置一定不能等于这个串的值 ans=simga{i,C(i- ...