【数据结构】什么是平衡二叉搜索树(AVL树)?

news2024/11/19 0:48:26

🦄个人主页:修修修也

🎏所属专栏:数据结构

⚙️操作环境:Visual Studio 2022


目录

📌AVL树的概念

📌AVL树的操作

🎏AVL树的插入操作

↩️右单旋

↩️↪️右左双旋

↪️↩️左右双旋

↪️左单旋

🎏AVL树的删除操作

结语


📌AVL树的概念

        我们之前一起学习过二叉搜索树,知道它具有较好的搜索性能, 但是普通的二叉搜索树会有一个问题,那就是它可能会因为输入的值不够随机,也可能因为经过某些插入或删除的操作,导致其失去平衡退化为单支树并导致搜索效率降低的情况, 如下不平衡搜索树:

        可以发现,如果搜索二叉树退化到这样极端的不平衡状态,其搜索效率就会大大降低, 时间复杂度会从O(log_{2}N)退化到O(N).为了解决这种情况,我们将引入AVL树的概念.

        AVL树是一个 “加上了额外平衡条件” 的二叉搜索树。其平衡条件的建立是为了确保整棵树的深度为O(log_{2}N)。直观上的最佳平衡条件是每个节点的左右子树有着相同的高度,但这未免太过严苛,我们很难插入新元素而又保持这样的平衡条件。AVL树于是退而求其次,要求任何节点的左右子树高度相差最多1。这是一个较弱的条件,但仍能够保证“对数深度(logarithmic depth)”平衡状态。

        因此, AVL树是一种二叉搜索树, 其中每一个结点的左子树和右子树的高度差至多等于1。我们将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF(Balance Factor), 那么平衡二叉树上所有结点的平衡因子只可能是-1/ 0/ 1.

        


📌AVL树的操作

🎏AVL树的插入操作

        我们知道,对于一颗AVL树而言,新插入的结点是很有可能破坏其平衡结构的,如:

        那么AVL树是如何解决这种情况的呢?下面我将通过模拟一组AVL树结点的插入来讲清楚AVL树是如何维持其平衡特性的.

        下面我们将以这组数据为例,详细剖析一下AVL树维持其平衡的插入过程:

14 9 5 17 11 12 7 19 16 27

        首先我们插入第一个结点14:

        然后我们插入第二个结点9:

        此时AVL树仍然是平衡状态,然后我们插入下一个结点5:

        可以看到,插入结点5之后,AVL树的根节点14就已经不满足平衡搜索二叉树的条件了,即它左子树的高度减去右子树的高度已经大于1,因此我们下面就要运用AVL树对不平衡的第一种处理方式,也就是右单旋:

↩️右单旋

        右单旋处理应用的情况为:

  • 失衡结点平衡因子 = 2
  • 失衡结点左孩子平衡因子 = 1

        右单旋的处理操作步骤为:

  • 将失衡结点左孩子的右子树链接到失衡结点的左孩子的位置
  • 将失衡结点链接到失衡结点左孩子的右孩子位置

        所以我们下面采取右单旋的方式使AVL树重新平衡, 因为失衡结点14的左孩子9并没有右孩子,所以我们可以直接将失衡结点14链接到失衡结点左孩子9的右孩子位置, 右单旋示意图如下:

        经过右单旋操作之后,我们得到的AVL树就又重新满足平衡二叉搜索树了:

        接下来我们继续插入新结点17:

        再继续插入新结点11:

        再继续插入新结点12:

        可以看到,插入结点12之后,AVL树的根节点9就已经不满足平衡搜索二叉树的条件了,即它左子树的高度减去右子树的高度已经成了-2,因此我们下面就要运用AVL树对不平衡的第二种处理方式,也就是右左双旋:

↩️↪️右左双旋

        右左双旋处理应用的情况为:

  • 失衡结点平衡因子 = -2
  • 失衡结点右孩子平衡因子 = 1

        右左双旋的处理操作步骤为:

  • 将失衡结点的右孩子右单旋
  • 再将失衡结点左单旋

        所以我们下面采取右左双旋的方式使AVL树重新平衡, 我们先将失衡结点9的右孩子14进行右单旋, 再将失衡结点9进行左单旋,右左双旋操作示意图如下:

         经过右左双旋操作之后,我们得到的AVL树就又重新满足平衡二叉搜索树了:

        我们继续插入新结点7:

         可以看到,插入结点7之后,AVL树的节点9就已经不满足平衡搜索二叉树的条件了,即它左子树的高度减去右子树的高度已经成了2,因此我们下面就要运用AVL树对不平衡的第三种处理方式,也就是左右双旋:

↪️↩️左右双旋

        左右双旋处理应用的情况为:

  • 失衡结点平衡因子 = 2
  • 失衡结点左孩子平衡因子 = -1

        左右双旋的处理操作步骤为:

  • 将失衡结点的左孩子左单旋
  • 再将失衡结点右单旋

        所以我们下面采取左右双旋的方式使AVL树重新平衡, 我们先将失衡结点9的左孩子5进行左单旋, 再将失衡结点9进行右单旋,左右双旋操作示意图如下:

        经过左右双旋操作之后,我们得到的AVL树就又重新满足平衡二叉搜索树了:

        然后我们继续插入新结点19:

         继续插入新结点16:

        最后插入结点27:

        可以看到,插入结点27之后我们发现AVL树的根节点11和其右孩子14都失衡了.这个时候我们只需要调整距离新插入结点最近的失衡结点即可,调整完这个最近失衡结点之后,其余的祖先失衡结点会自动恢复平衡的。我们下面就要运用AVL树对不平衡的第四种处理方式,也就是左单旋:

↪️左单旋

        左单旋处理应用的情况为:

  • 失衡结点平衡因子 = -2
  • 失衡结点右孩子平衡因子 = -1

        左单旋的处理操作步骤为:

  • 将失衡结点右孩子的左子树链接到失衡结点的右孩子的位置
  • 将失衡结点链接到失衡结点右孩子的左孩子位置

        所以我们下面采取左单旋的方式使AVL树重新平衡, 先将失衡结点14的右孩子17的右子树16链接到失衡结点14的右孩子的位置,再将失衡结点14链接到失衡结点右孩子17的左孩子位置, 左单旋示意图如下:

          经过左单旋操作之后,我们得到的AVL树就完成了所有的插入操作并满足平衡二叉搜索树了:

         在经历了四种旋转操作之后,我们将旋转的方式以及其对应的影响因子的特征总结如下:


🎏AVL树的删除操作

        前面讲了AVL树的插入操作需要保证其不失衡, 对于AVL树的删除操作来说也一样, 同样需要保证其操作后树不失衡, 和插入操作不同的是, 删除操作可能会导致不只一次的失衡, 所以我们不能像插入那样调节最近的失衡结点就行, 在删除时可以参考之前讲过的二叉搜索树的删除操作,但是AVL树在删除之后需要沿着祖先结点一直向上继续查找是否有结点失衡的情况,如果有,就需要进行旋转调整,其旋转规则和插入时我们总结的影响因子特征相同。

        下图附上二叉搜索树的删除逻辑,有兴趣的朋友可以自行研究一下:


结语

希望这篇关于 平衡二叉搜索树(AVL树) 的博客能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【C++】STL标准模板库容器map

【C++】STL标准模板库容器set

【C++】模拟实现二叉搜索(排序)树

【数据结构】C语言实现链式二叉树(附完整运行代码)

【数据结构】什么是二叉搜索(排序)树?

【C++】模拟实现priority_queue(优先级队列)

【C++】模拟实现queue

【C++】模拟实现stack

【C++】模拟实现list

【C++】模拟实现vector

【C++】标准库类型vector

【C++】模拟实现string类

【C++】标准库类型string

【C++】构建第一个C++类:Date类

【C++】类的六大默认成员函数及其特性(万字详解)

【C++】什么是类与对象?


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2177696.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用AI十分钟制作视频,暴涨4.7w粉丝,小白也能月入过万

今天给大家展示的项目是:AI动漫人物封面。 先来看一下教程方的广告: 蓝海赛道、AI翻唱 一周内获得了4.7万个粉丝,小白也可以轻松上手,月入过万手拿把掐。 现在利用AI创作 动漫 IP 翻唱音乐在全网悄然增多,流量也非常…

女性向游戏的新战场:AI陪伴系统

在数字化时代,游戏不再只是简单的娱乐产品,而是成为了人们情感寄托的重要载体。特别是对于女性玩家来说,游戏不仅仅是一种消遣,更是一种情感体验。近年来,女性向游戏市场逐渐崛起,其中“陪伴系统”成为了一…

【LeetCode】动态规划—931. 下降路径最小和(附完整Python/C++代码)

动态规划—931. 下降路径最小和 前言题目描述基本思路1. 问题定义2. 理解问题和递推关系3. 解决方法3.1 动态规划方法3.2 空间优化的动态规划 4. 进一步优化4.1 空间复杂度优化 5. 小总结 代码实现Python3代码实现Python 代码解释C代码实现C 代码解释 总结: 前言 在算法的学习…

985官宣:19名本科生,获国自然项目!

9月24日,据复旦大学教务处消息,国家自然科学基金委公布了2024年国家自然科学基金青年学生基础研究项目(本科生)立项情况,复旦大学共有19名基础学科专业本科生获得国家自然科学基金委资助。 此前,据武汉大学…

VBA技术资料MF207:右键录入指定范围数据

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…

比较器(算法中排序)

方式一&#xff1a;不常用 让实体类实现Comparable接口&#xff0c;泛型是需要比较的类型&#xff0c;同时重写compareTo方法 缺点&#xff1a;对代码有侵入性。 public class Student implements Comparable<Student> {private String name;private double score;// …

【YOLOv10改进[SPPF]】使用 SPPFCSPC替换SPPF模块 + 含全部代码和详细修改方式

本文将进行在YOLOv10中使用SPPFCSPC魔改v10 的实践,文中含全部代码、详细修改方式。助您轻松理解改进的方法。 改进前和改进后的参数对比如下: 目录 一 SPPFCSPC 二 使用SPPFCSPC魔改v10的实践 1 整体修改 ① 添加SPPCSPC.py文件 ② 修改ultralytics/nn/tasks.py文件

java中使用selenium自动化测试

一、查看你Chrome浏览器的版本 在浏览器的地址栏&#xff0c;输入chrome://version/&#xff0c;回车后即可查看到对应版本 二、找到对应的chromedriver版本 2.1 114及之前的版本可以通过点击下载chromedriver,根据版本号&#xff08;只看大版本&#xff09;下载对应文件 2.…

运维监控平台:监控易如何实现运维高效管理与大规模监控

在快速变化的数字时代&#xff0c;运维团队正面临着前所未有的挑战。随着企业规模的扩大和IT架构的复杂化&#xff0c;运维团队需要管理的设备数量激增&#xff0c;对系统的稳定性和扩展性提出了更高要求。在这样的背景下&#xff0c;如何高效地进行设备监控&#xff0c;确保系…

pdf分割成多个文件怎么弄?这6个技巧教您学会pdf分割,一看就会!

pdf分割成多个文件怎么弄pdf文件分割成多个文件的需求在办公场景中非常常见。您是否也曾为处理含有多个页面的pdf文件而感到烦恼&#xff1f;不用担心&#xff01;在这篇文章中&#xff0c;小编将和大家分享六个简单易懂的技巧&#xff0c;教您如何轻松将pdf拆分成一页一页的单…

本省第一所!新大学,揭牌!

9月26日&#xff0c;海南艺术职业学院举行揭牌仪式&#xff0c;标志着海南省第一所公办艺术类高等职业院校正式揭牌成立。海南省旅文厅党组成员、副厅长刘成出席揭牌仪式&#xff0c;省教育厅党组成员、副厅长邢孔政在揭牌仪式上宣读省人民政府同意设立海南艺术职业学院的批复。…

【操作系统】三、内存管理:1.存储器管理(程序装入与链接;逻辑地址与物理地址空间;内存保护;交换与覆盖;分页管理方式;分段管理方式;段页式管理方式)

三、内存管理 文章目录 三、内存管理内存基础知识1.分类1.1按在计算机中的作用&#xff08;层次&#xff09;1.2按存储介质1.3按存取方式1.4按信息的可更改性1.5按信息的可保存性 2.存储器的性能指标 六、存储器管理&#xff08;内存管理基础&#xff09;0.内存保护1.程序到程序…

4--苍穹外码-SpringBoot项目中分类管理 详解

前言 1--苍穹外卖-SpringBoot项目介绍及环境搭建 详解-CSDN博客 2--苍穹外卖-SpringBoot项目中员工管理 详解&#xff08;一&#xff09;-CSDN博客 3--苍穹外卖-SpringBoot项目中员工管理 详解&#xff08;二&#xff09;-CSDN博客 4--苍穹外码-SpringBoot项目中分类管理 详…

webGL入门(四)绘制一个三角形

代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><scri…

DBMS-2.3 数据库设计(3)——数据库规范化设计实现(3NF、BCNF模式分解)

本文章的素材与知识来自李国良老师和王珊珊老师。 关系模式分解的定义 一.关系模式分解的定义 1.定义 2.理解 &#xff08;1&#xff09;关系不丢失&#xff1a;所有子关系的属性集加起来 原关系的属性集。即分解中不能把某个属性给丢了。 &#xff08;2&#xff09;模式…

8.6K Star,一键将 Markdown 可视化为思维导图

Hi&#xff0c;骚年&#xff0c;我是大 G&#xff0c;公众号「GitHub 指北」会推荐 GitHub 上有趣有用的项目&#xff0c;一分钟 get 一个优秀的开源项目&#xff0c;挖掘开源的价值&#xff0c;欢迎关注。 在知识管理和项目规划中&#xff0c;思维导图是非常有效的工具&#…

【Flume Kafaka实战】Using Kafka with Flume

一 目标 在Cloudera Manager中创建两个Flume的Agent&#xff0c;Agent1从local file中获取内容&#xff0c;写入到kafka的队列中。Agent2以Agent1的sink作为source&#xff0c;将数据从kafka中读取出来&#xff0c;写入到HDFS中。 二 实战 2.1 Kafka Sink 第一步&#xff0…

Java-数据类型与变量

一、字面常量 在我们使用Java进行数据的打印时&#xff0c;经常会用到这个语句&#xff1a; System.out.println("Hello world!"); 而当这个语句运行时&#xff0c;不论如何都会输出"Hello world!"&#xff0c;所以"Hello world!"就是字面常量…

哪款宠物空气净化器能有效去除浮毛?希喂、352实测分享

你是否曾经站在家电卖场里&#xff0c;面对琳琅满目的宠物空气净化器产品而感到无所适从&#xff1f;或者在浏览网上商城时&#xff0c;被海量的参数和功能描述搞得头晕眼花&#xff1f;别担心&#xff0c;你不是一个人。在这个科技飞速发展的时代&#xff0c;选择一台既能满足…