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 点 链 重点! 树 树 简单, 线 ...
随机推荐
- deeplearning 重要调参参数分析
reference: https://blog.csdn.net/jningwei/article/details/79243800 learning rate:学习率,控制模型的学习进度,决定权值更 ...
- 眼底血管分割训练函数(SVM,Adaboost)
# -*- coding: utf-8 -*- import numpy as np from sklearn import svm from sklearn.model_selection impo ...
- 20165328 学习基础和C语言基础调查
一.技能学习经验: 1.你有什么技能比大多数人(超过90%以上)更好: 我算是一个普通人,没什么特别的才能,如果硬要说有什么技能比其他人较好的话,我想大概是快速阅读的能力吧,我能以很快的速度 ...
- Nginx限制下载速度
http { limit_conn_zone $binary_remote_addr zone=one:10m; #容器共使用10M的内存来对于IP传输开销 server { lis ...
- linux操作系统中oracle数据库的密码过期问题解决
1:首先确定linux登录的用户是root 切换到数据库用户 su oracle(切记,如果这里su oracle不可以,那么就使用此命令su - oracle,这个命令切换到数据库用户肯定可以成功. ...
- 利用 Windows API Code Pack 修改音乐的 ID3 信息
朋友由于抠门 SD 卡买小了,结果音乐太多放不下,又不舍得再买新卡,不得已决定重新转码,把音乐码率压低一点,牺牲点音质来换空间(用某些人的话说,反正不是搞音乐的,听不出差别)… 结果千千静听(百度音乐 ...
- mysql表管理
4.1 查看所有表 查看所有表语句: show tables; 例: mysql> show tables; +-----------------+ | Tables_in_emp | +--- ...
- Asp.net 与 UCenter 用户同步之实施过程
在写这篇文章的时候,我还在想,这篇文章也许能给你带来一些收获,但或许会令你更加的迷茫,为什么会这样?因为:1.UCenter虽然足够强大,但正为它的强大,它的不少暗箱操作使得我们望而生畏,我们不害怕出 ...
- Python_collections_namedtuple可命名元组
namedtuple:用来构建带字段名的元组 import collections # 创建类,两种创建方法 MytupleClass = collections.namedtuple('Mytupl ...
- admin密码对应的MD5值
admin密码对应的MD5值,16位和32位 admin密码对应的MD5值,16位和32位 admin的md5值是多少,常用密码加密md5值,123456,admin,admin888 如果遇到MD5 ...