图解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 ...
随机推荐
- 百道Python面试题实现,搞定Python编程就靠它
对于一般的机器学习求职者而言,最基础的就是掌握 Python 编程技巧,随后才是相关算法或知识点的掌握.在这篇文章中,我们将介绍一个 Python 练习题项目,它从算法练习题到机试实战题提供了众多问题 ...
- 【原创】Linux select/poll机制原理分析
前言 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 1. 概述 Linux系统 ...
- 045.集群存储-CSI存储机制
一 CSI存储机制 1.1 CSI简介 Kubernetes从1.9版本开始引入容器存储接口Container Storage Interface(CSI)机制,用于在Kubernetes和外部存储系 ...
- WeChat-SmallProgram:引用页面调用组件内的方法
如何创建组件 及 使用 这里不在多说:请参考之前文章 如何定义一个组件 自定义select下拉选项框组件使用 引用组件: <sub-unit-select id="init" ...
- Python python 函数参数:可变参数
# 可变参数 '''传入的参数数量是不确定的 ''' '''若是要计算几个数(未知)的平方和 ''' def cal(nums): sum = 0 for num in nums: sum = sum ...
- logstash用jdbc插件将数据库内容导入elasticsearch时间字段相差5小时
logstash将mysql的数据导入elasticsearch之后发现时间字段的相差5个小时 解决办法: 在数据库连接配置后面加上?serverTimezone=UCT这个就OK了 logstash ...
- Javascript/Jquery遇到字符串自动NaN的问题
结果发现是一个id绑定了两次点击事件.修改之后,问题解决.
- IDEA 新版本激活之后老是有弹窗 解决方法
用了最新的版本的IDEA,然后用网上的方法破解到了2089年,但是打开IDEA的时候,老是出现一个弹窗,内容如下: This agent is for learning and research pu ...
- O - 推箱子 HDU - 1254(bfs_box + bfs_man)
O - 推箱子 HDU - 1254 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能 ...
- UnboundLocalError,探讨Python中的绑定
绑定 将python闭包之前,先梳理一下闭包中的绑定操作. 先看看2个相关的错误 NameError 和UnboundLocalError When a name is not found at al ...