图解AVL树
1:AVL树简介
二叉搜索树在一般情况下其搜索的时间复杂度为O(logn),但某些特殊情况下会退化为链表,导致树的高度变大且搜索的时间复杂度变为O(n),发挥不出树这种数据结构的优势,因此平衡二叉树便应运而生,通过保证树的高度来保证查询的时间复杂度为O(logn),想想人类实在是太聪明了!
2:构造AVL树
在构造一棵AVL树的时候如何保持平衡呢?其手段便是通过各种旋转变换来调整以此保证整棵树的高度,调整的原则是左右子树的高度不能大于1的绝对值(平衡因子)先来介绍下旋转的方法吧。
2.1:LL型
当插入元素后构成LL型,如下图所示,则以2为支,高右转,把3右旋下来保证平衡。
2.2:RR型
当插入元素后构成RR型,如下图所示,则以2为支,高左转,把1左旋转下来保证平衡。
2.3:LR型
当插入元素后构成LR型,如下图所示,先2,3整体左旋,在根据LL型进行右旋转来保证平衡。
2.4:RL型
当插入元素后构成RL型,如下图所示,先将5右转,在与6进行交换,在根据RR型进行旋转来保证平衡。
2.5:其他情况
当因为插入一个元素而导致出现两个不平衡点,应该调整距离插入节点最近的不平衡点
2.6:自测题
测试题:以关键字序列{16、3、7、11、9、26、18、14、15}构造一颗AVL树
2.7:java实现AVL的构造
package AVL;
/**
* @author admin
* @version 1.0.0
* @ClassName AVLTree.java
* @Description TODO
* @createTime 2020年03月30日 18:28:00
*/
public class AVLTree {
/**
* 获取左右节点的高度差,即平衡因子
* @param root
* @return
*/
public int getBalance(Node root) {
return root==null?0:getHeight(root.left)-getHeight(root.right);
}
/**
* 获取节点的高度
* @param root
* @return
*/
public int getHeight(Node root) {
return root == null ? 0 : root.height;
}
/**
* 更新节点的高度
* @param root
* @return
*/
private int updateHeight(Node root) {
if (root == null)
return 0;
return Math.max(updateHeight(root.left), updateHeight(root.right)) + 1;
}
/**
* LL型,右旋操作
*
* @param root
* @return
*/
public Node rightRotate(Node root) {
Node node = root.left;
root.left = node.right;
node.right = root;
root.height = updateHeight(root);
node.height = updateHeight(node);
return node;
}
/**
* RR型,左旋操作
* @param root
* @return
*/
public Node leftRotate(Node root) {
Node node = root.right;
root.right = node.left;
node.left = root;
root.height = updateHeight(root);
node.height = updateHeight(node);
return node;
}
public Node insert(Node node, int data) {
//当节点为空,直接插入
if (node == null) {
return (new Node(data));
}
//当插入元素<node.data,往node的左子树进行插入;>node.data,往node的右子树插入
if (node.data > data) {
node.left = insert(node.left, data);
} else {
node.right = insert(node.right, data);
}
//更新节点的高度
node.height = updateHeight(node);
//获取平衡因子(左子树高度-右子树高度)
int balDiff = getBalance(node);
// 右旋
if (balDiff > 1 && data < node.left.data) {
return rightRotate(node);
}
// 左旋
if (balDiff < -1 && data > node.right.data) {
return leftRotate(node);
}
// 先左旋在右旋
if (balDiff > 1 && data > node.left.data) {
node.left = leftRotate(node.left);
return rightRotate(node);
}
// 先右旋在左旋
if (balDiff < -1 && data < node.right.data) {
node.right = rightRotate(node.right);
return leftRotate(node);
}
return node;
}
}
class Node {
int data;
Node left;
Node right;
int height;
public Node(Integer data) {
this.data = data;
height = 1;
}
}
3:AVL树的删除
3.1:删除叶子节点
3.2:删除只拥有左子树或右子树的节点
3.3:删除既拥有左子树又有右子树的节点
3.4:自测题
将上一道自测题的图依次删除16,15,11节点,画出最后的结果
参考链接
数据可视化网站: https://visualgo.net/zh
哔哩哔哩讲AVL:https://www.bilibili.com/video/BV1xE411h7dd
图解AVL树的更多相关文章
- AVL树的插入操作(旋转)图解
=================================================================== AVL树的概念 在说AVL树的概念之前,我们需要清楚 ...
- 平衡二叉树,AVL树之图解篇
学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...
- 图解数据结构树之AVL树
AVL树(平衡二叉树): AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.在AVL树中任何节点的两个子 ...
- 二叉搜索树的平衡--AVL树和树的旋转(图解)
二叉搜索树只有保持平衡时其查找效率才会高. 要保持二叉搜索树的平衡不是一件易事.不过还是有一些非常经典的办法可以做到,其中最好的方法就是将二叉搜索树实现为AVL树. AVL树得名于它的发明者 G.M. ...
- 图解:平衡二叉树,AVL树
学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...
- 二叉树之AVL树的平衡实现(递归与非递归)
这篇文章用来复习AVL的平衡操作,分别会介绍其旋转操作的递归与非递归实现,但是最终带有插入示例的版本会以递归呈现. 下面这张图绘制了需要旋转操作的8种情况.(我要给做这张图的兄弟一个赞)后面会给出这八 ...
- AVL树平衡旋转详解
AVL树平衡旋转详解 概述 AVL树又叫做平衡二叉树.前言部分我也有说到,AVL树的前提是二叉排序树(BST或叫做二叉查找树).由于在生成BST树的过程中可能会出现线型树结构,比如插入的顺序是:1, ...
- AVL树(查找、插入、删除)——C语言
AVL树 平衡二叉查找树(Self-balancing binary search tree)又被称为AVL树(AVL树是根据它的发明者G. M. Adelson-Velskii和E. M. Land ...
- 算法与数据结构(十一) 平衡二叉树(AVL树)
今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...
随机推荐
- WEB缓存控制机制与varnish简介
在说到缓存varnish前,我们首先来了解下对于web服务缓存到底是什么?它有哪些特点,基础原理是什么? http是web应用协议,通常我们说的一次http事务,不外乎就是客户端请求,服务端响应,通常 ...
- 莎士比亚电路ヾ(≧▽≦*)o
偶尔记录一件有趣的事儿! 这个电路叫做 "莎士比亚电路"[1],请自行参悟,ヾ(≧▽≦)o,ヾ(≧▽≦)o,ヾ(≧▽≦*)o ヾ(≧▽≦*)o . <穿越计算机的迷雾> ...
- Google浏览器截取整个网页
~Ctrl+shift+i(开发者工具) ~Ctrl+shift+p ~输入full
- Material Design 组件之 CollapsingToolbarLayout
CollapsingToolbarLayout 主要用于实现一个可折叠的标题栏,一般作为 AppBarLayout 的子 View 来使用,下面总结一下 CollapsingToolbarLayout ...
- Light of future-冲刺Day 6
目录 1.SCRUM部分: 每个成员进度 SCRUM 会议的照片 签入记录 代码运行截图 用户浏览界面 订单详情界面 管理员浏览界面 新增后台界面 2.PM 报告: 时间表 燃尽图 任务总量变化曲线 ...
- 各种版本docker下载的中国开源地址
最近在群里听说Docker很火,于是自己抱着试试的态度,想玩玩,可是遇到了一些问题,记录下来,方便备忘,也方便防止大家被坑. 我的虚拟机装的是centos 6.5,百度了好多教程,丫的,都不解释,就一 ...
- 混合app禁止切换输入法英文键盘方案
前言 在此介绍的是h5的部分,非原生,原生可以直接属性禁止. 需求 禁止中文出现在input中.(如果你认为不显示出来中文,那么请往下看) 效果:只显示英文键盘. 遇到的问题 1.在三星低版本上会出现 ...
- Android视频悬浮窗口实现
前言 本文例子实现了点击显示悬浮窗口,同时窗口可播放视频,拖动位置,点击关闭及返回APP页面,通过例子来讲述悬浮窗口实现原理及细节处理,效果图如下所示: 原理 WindowManager对View视图 ...
- 解决:docker-compose端口绑定
docker-compose 进程绑定 Bind for 0.0.0.0:3825 failed: port is already allocated 查看进程发现有进程在关闭后继续进行 docker ...
- python 函数--迭代器
一.迭代协议: 可以被迭代要满足要求的就叫做可迭代协议.内部实现__iter__方法. iterable:可迭代的--对应的标志. 什么叫做迭代?:可以一个一个取值,就像for循环一样取值. 字符串, ...