简介

基本概念

AVL 树是最早被发明的自平衡的二叉查找树,在 AVL 树中,任意结点的两个子树的高度最大差别为 1,所以它也被称为高度平衡树,其本质仍然是一颗二叉查找树。

结合二叉查找树,AVL 树具有以下特性:

  • 若任意结点的左子树不为空,则左子树上所有结点的值均小于它的根结点的值
  • 若任意结点的右子树不为空,则右子树上所有结点的值均大于或等于它的根结点的值
  • 任意结点的左、右子树也分别为二叉查找树
  • 任意结点的子树的高度差都小于等于 1

上述的前三项都是二叉查找树的特性,第四个是 AVL 树自平衡的特性。

实现原理

为了保证二叉树的平衡,AVL 树引入了监督机制,就是在树的某一部分的不平衡度超过一个阈值后触发相应的平衡操作,保证树的平衡度在可以接受的范围内。

既然引入了监督机制,则必然需要一个监督指标,以此来判断是否需要进行平衡操作。这个监督指标被称为平衡因子(Balance Factor)。定义如下:

某个结点的右子树的高度减去左子树的高度得到的差值。

基于平衡因子,就可以这样定义 AVL 树:

所有结点的平衡因子的绝对值都不超过 1 的二叉查找树。

为了计算平衡因子,自然需要在结点中引入高度这一属性。结点的高度为以下定义:

左右子树的高度的最大值。

class AVLNode {
AVLNode left; // 左子树
AVLNode right; // 右子树
int height; // 当前结点的高度
int value; // 当前结点的值
}

自平衡

自平衡是指在对平衡二叉树执行插入或删除结点操作后,可能会导致树中某个结点的平衡因子绝对值超过 1,即平衡二叉树变得“不平衡”,为了恢复该结点左右子树的平衡,此时需要对结点执行旋转操作。

二叉树的平衡化有两大基础操作: 左旋和右旋。左旋,即是逆时针旋转;右旋,即是顺时针旋转。

这两种操作都是从失去平衡的最小子树根结点开始的(即离插入结点最近且平衡因子超过 1 的祖结点)。

左旋

所谓左旋操作,就是把上图中的 B 结点和 A 结点进行所谓“父子交换”。在仅有这三个结点时候,是十分简单的。但是当 B 结点处存在左孩子时,事情就变得有点复杂了。

通常的操作是:结点 B 抛弃左孩子,将之与旋转后的结点 A 相连,成为结点 A 的右孩子。

右旋

所谓右旋操作,就是把上图中的 B 结点和 C 结点进行所谓“父子交换”。在仅有这三个结点时候,也是是十分简单的。但是当 B 结点处存在右孩子时,事情就变得有点复杂了。

这时通常的操作是:结点 B 抛弃右孩子,将之和旋转后的结点 C 相连,成为结点 C 的左孩子。

单次旋转 - LL

LL 型又被称为“左左”,从上图中可以看得出,A 结点的平衡因子绝对值达到了 2,需要进行修复才能重新成为一棵平衡二叉树。F 结点为新插入的结点,优先会经过 A 结点的左孩子 B 结点,最终落到 B 结点的左子树上,这即是“左左”的来由。

可以使用平衡因子来定义 LL 情况:A 结点的平衡因子为 -2,左孩子 B 结点的平衡因子为 -1。

这时候仅需要对 A 结点做一次右旋的操作即可达到平衡状态:

单次旋转 - RR

RR 型又被称为“右右”,与上面的 LL 型 具有对称性,展示的情况如下:

也可以使用平衡因子来定义:A 结点的平衡因子为 2,右孩子 C 结点的平衡因子为 1。

这里则是仅需要对 A 结点做一次左旋的操作即可达到平衡状态:

双次旋转 - LR

使用平衡因子定义 LR 型为:A 结点的平衡因子为 -2,左孩子 B 结点的平衡因子为 1。

下面有一个例子:

第一步:对 A 结点的左子结点 —— B 结点执行左旋操作,得到一个 LL 型的结构:

第二步:对 A 结点执行右旋操作:

双次旋转 - RL

RL 型和上面的 LR 型对称,A 结点的平衡因子为 2,右孩子 C 结点的平衡因子为 -1。

第一步:对 A 结点的右子结点 —— C 结点执行右旋操作,得到一个 RR 型的结构:

第二步:对 A 结点执行左旋操作:

数据结构 - AVL 树的更多相关文章

  1. 数据结构-AVL树的旋转

    http://blog.csdn.net/GabrieL1026/article/details/6311339 平衡二叉树在进行插入操作的时候可能出现不平衡的情况,AVL树即是一种自平衡的二叉树,它 ...

  2. 简单数据结构———AVL树

    C - 万恶的二叉树 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     64b ...

  3. JAVA数据结构--AVL树的实现

    AVL树的定义 在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下的时间复杂度都是.增 ...

  4. 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作

    AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树.   2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1).   也就是说,AVL树,本质上 ...

  5. 再回首数据结构—AVL树(一)

    前面所讲的二叉搜索树有个比较严重致命的问题就是极端情况下当数据以排序好的顺序创建搜索树此时二叉搜索树将退化为链表结构因此性能也大幅度下降,因此为了解决此问题我们下面要介绍的与二叉搜索树非常类似的结构就 ...

  6. 再回首数据结构—AVL树(二)

    前面主要介绍了AVL的基本概念与结构,下面开始详细介绍AVL的实现细节: AVL树实现的关键点 AVL树与二叉搜索树结构类似,但又有些细微的区别,从上面AVL树的介绍我们知道它需要维护其左右节点平衡, ...

  7. 第三十二篇 玩转数据结构——AVL树(AVL Tree)

          1.. 平衡二叉树 平衡二叉树要求,对于任意一个节点,左子树和右子树的高度差不能超过1. 平衡二叉树的高度和节点数量之间的关系也是O(logn) 为二叉树标注节点高度并计算平衡因子 AVL ...

  8. Java数据结构——AVL树

    AVL树(平衡二叉树)定义 AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,并且拥有自平衡机制.在AV ...

  9. 数据结构-AVL树

    实现: #ifndef AVL_TREE_H #define AVL_TREE_H #include "dsexceptions.h" #include <iostream& ...

随机推荐

  1. sqli-labs下载与安装

    Sqli-labs 下载 Sqli-labs是一个印度程序员写的,用来学习sql注入的一个游戏教程. 博客地址为:http://dummy2dummies.blogspot.hk/, 博客当中有一些示 ...

  2. 解决centos7服务器shadows已启动但是无法连接的问题

    firewall-cmd --permanent --add-port=8989/tcp firewall-cmd --reload 这是由于centos7防火墙并没有开放ss端口的问题 添加json ...

  3. Acwing 社交距离 分类讨论+贪心

    一种新型疾病,COWVID-19,开始在全世界的奶牛之间传播. Farmer John 正在采取尽可能多的预防措施来防止他的牛群被感染. Farmer John 的牛棚是一个狭长的建筑物,有一排共 N ...

  4. 手把手带你使用EFR32 -- 土壤湿度传感器变身第二形态,以 ZigBee 形态出击

    前言 后悔,总之就是非常后悔,我当时到底是为啥才会猪油蒙心,选择了 EFR32 来学习 ZigBee 使用啊? EFR32 这玩意看性能确实不错,但是资料太少了,EmberZnet SDK 也是用得一 ...

  5. 如何处理异形屏iphone X?

    safe area: 默认放置在安全区域以避免遮挡, 但会压缩 在meta中添加viewport-fit=cover: 告诉浏览器要讲整个页面渲染到浏览器中,不管设备是圆角与否,这个时候会造成页面的元 ...

  6. B树、B+树、B*树三者的对比详解

    转载至:https://www.2cto.com/database/201805/745822.html 对比 B+树是B树的变体,B*树又是B+树的变体,是一脉相承法治国拉的,不断解决新一阶段的问题 ...

  7. 我们如何监视所有 Spring Boot 微服务?

    Spring Boot 提供监视器端点以监控各个微服务的度量.这些端点对于获取有关应用程序的信息(如它们是否已启动)以及它们的组件(如数据库等)是否正常运行很有帮助.但是,使用监视器的一个主要缺点或困 ...

  8. Vue中data数据,使用v-model属性绑定第三方插件(例如Jquery的日期插件)无法自动更新

    问题原因就是html结合Vue使用,但是项目又使用了第三方日期控件,这会导致日期值选择形式的更新后,而Vue管理的对应v-model字段并未自动更新,这是因为日期控件未触发Input事件,需要我们在值 ...

  9. 转:master公式(主方法)

    master公式(也称主方法)是利用分治策略来解决问题经常使用的时间复杂度的分析方法,(补充:分治策略的递归解法还有两个常用的方法叫做代入法和递归树法),众所众知,分治策略中使用递归来求解问题分为三步 ...

  10. Elasticsearch 是如何实现 Master 选举的?

    1.Elasticsearch 的选主是 ZenDiscovery 模块负责的,主要包含 Ping(节点之 间通过这个 RPC 来发现彼此)和 Unicast(单播模块包含一个主机列表以控制哪 些节点 ...