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

news2024/11/25 2:24:22

🦄个人主页:修修修也

🎏所属专栏:数据结构

⚙️操作环境: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/2186353.html

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

相关文章

CTF刷题buuctf

[WUSTCTF2020]颜值成绩查询 拿到相关题目,其实根据功能和参数分析。需要传入一个学号然后进行针对于对应的学号进行一个查询,很可能就会存在sql注入。 其实这道题最难的点,在于过滤了空格,因此我们使用 /**/来过滤空格的限制。…

智能化焊接数据管理系统:系统功能设计与应用场景,OEM定制

在快速发展的工业4.0时代,智能化技术正以前所未有的速度改变着各行各业,其中焊接行业也不例外。随着物联网、大数据、人工智能等技术的不断融合,智能化焊接数据管理系统应运而生,成为提高焊接效率、保障焊接质量、优化生产流程的重…

半监督学习与数据增强(论文复现)

半监督学习与数据增强(论文复现) 本文所涉及所有资源均在传知代码平台可获取 文章目录 半监督学习与数据增强(论文复现)概述算法原理核心逻辑效果演示使用方式 概述 本文复现论文提出的半监督学习方法,半监督学习&…

C题(二)字符串转数字 --- atoi

———————————————————**目录**—————————————————— 一、 atoi函数介绍 功能函数原型使用示例 二、题解之一 三、留言 问题引入👉 输入样例👉 5 01234 00123 00012 00001 00000 输出样例👉 1234 123 …

‌文件名称与扩展名:批量重命名的技巧与指南

在日常的文件管理中,我们经常需要处理大量的文件,这些文件可能有着各种各样的名称和扩展名。为了更好地管理和识别这些文件,批量重命名成为了一项非常实用的技能。能够帮助我们快速整理文件,提高工作效率。本文将深入探讨文件名称…

vue2圆形标记(Marker)添加点击事件不弹出信息窗体(InfoWindow)的BUG解决

目录 一、问题详情 二、问题排查 三、解决方案 一、问题详情 地图上面的轨迹点希望能通过点击看到详细的经纬度信息,但是点击的时候就是显示不出来。 二、问题排查 代码都是参考高德的官方文档,初步看没有问题啊,但是点击事件就感觉失效…

10.3今日错题解析(软考)

目录 前言计算机网络——路由配置数据库系统——封锁协议 前言 这是用来记录我备考软考设计师的错题的,今天知识点为路由配置、封锁协议,大部分错题摘自希赛中的题目,但相关解析是原创,有自己的思考,为了复习&#xf…

Pix2Pix实现图像转换

tutorials/application/source_zh_cn/generative/pix2pix.ipynb MindSpore/docs - Gitee.com Pix2Pix概述 Pix2Pix是基于条件生成对抗网络(cGAN, Condition Generative Adversarial Networks )实现的一种深度学习图像转换模型,该模型是由Ph…

Comparable接口和Comparator接口

前言 Java中基本数据类型可以直接比较大小,但引用类型呢?同时引用对象中可能存在多个可比较的字段,那么我们该怎么比较呢? Java中引用类型不能直接进行大小的比较,这种行为在编译器看来是危险的,所以会编译…

程序员在AI时代的生存指南:打造不可替代的核心竞争力

在这个AI大行其道的时代,似乎每天都有新的语言模型像变魔术一样涌现出来,比如ChatGPT、midjourney、claude等等。这些家伙不仅会聊天,还能帮忙写代码,让程序员们感受到了前所未有的“压力”。我身边的一些程序员朋友开始焦虑&…

SpringCloud入门(十)统一网关Gateway

一、网关的作用 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。 …

E. Tree Pruning Codeforces Round 975 (Div. 2)

原题 E. Tree Pruning 解析 本题题意很简单, 思路也很好想到, 假设我们保留第 x 层的树叶, 那么对于深度大于 x 的所有节点都要被剪掉, 而深度小于 x 的节点, 如果没有子节点深度大于等于 x, 那么也要被删掉 在做这道题的时候, 有关于如何找到一个节点它的子节点能通到哪里,…

关于鸿蒙next 调用系统权限麦克风

使用app的时候都清楚,想使用麦克风、摄像头,存储照片等,都需要调用系统的权限,没有手机操作系统权限你也使用不了app所提供的功能,虽然app可以正常打开,但是你需要的功能是没办法使用的。今天把自己在鸿蒙学…

想怎样书写HTML5自结束标签,您随意就好(✪▽✪)

书写后接斜杠还是不接,看过ai给的详细解析就不再迷茫了。 (笔记模板由python脚本于2024年10月03日 10:42:41创建,本篇笔记适合HTML5标签的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖…

【数据库差异研究】update与delete使用表别名的研究

目录 ⚛️总结 ☪️1 Update ♋1.1 测试用例UPDATE users as a SET a.age 111 WHERE a.name Alice; ♏1.2 测试用例UPDATE users as a SET a.age 111 WHERE name Alice; ♐1.3 测试用例UPDATE users as a SET age 111 WHERE a.name Alice; ♑1.4 测试用例UPDATE us…

TIM“PWM”输出比较原理解析

PWM最重要的就是占空比,所有都是在为占空比服务,通过设置不同的占空比,产生不同的电压,产生不同的效果 定时器的输出通道 基本定时器: 基本定时器没有通道 通用定时器: 4个通道(CH1, CH2, C…

Python性能优化:实战技巧与最佳实践

Python性能优化:实战技巧与最佳实践 Python 作为一种动态解释型语言,虽然以其简洁和易用性闻名,但在性能方面可能不如静态编译型语言如 C 和 Java 高效。为了在高性能要求的应用场景下更好地利用 Python,我们需要掌握一些常见的优…

STM32GPIO输入和输出

一、先看IO端口位的结构 上面部分是输入,下面是输出。 1、I/O输入: 首先,从I/O引脚开始,有两个保护二极管,主要作用是对输入电压限幅,保护内部电路。上面二极管接VDD为3.3V,下面二极管接VSS为0V。当输入电…

认知杂谈71《创业抉择:定制化与标准化的权衡之路》

内容摘要: *嘿,彦祖们!今天来聊聊创业的事,创业选产品类型很关键。定制化产品如魔法,贴合客户需求但成本高且有边际递减风险。要掌握物联网技术,用 3D 建模软件,参考特定书籍,参加展…

在线JSON可视化工具--支持缩放

先前文章提到的超好用的JSON可视化工具,收到反馈,觉得工具好用,唯一不足就是不能缩放视图,其实是支持的,因为滚轮有可能是往下滚动,会与缩放冲突,所以这个工具设计为需要双击视图来触发打开缩放…