【数据结构】AVL树

文章目录

  • AVL树
    • 1. AVL树的概念
    • 2. AVL树节点的定义
    • 3. AVL树的插入
    • 4. AVL树的旋转

AVL树

1. AVL树的概念

二叉搜索树可以缩短查找的效率,但是如果数据接近有序二叉搜索树将会退化为单支,查找元素相当于在顺序表中搜索元素,效率低下。

当向二叉搜索树当中插入新节点后,保证每个节点的左右子树高度之差的绝对值不超过1(需要对树中的节点进行调整)即可降低树的高度,从而减少平均搜索长度

一棵AVL树或者空树:

  • 它的左右子树都是AVL树
  • 左右子树高度只差(简称平衡因子)的绝对值不超过1

如果一棵二叉搜索树的高度是平衡的,它就是AVL树。

平衡因子:左边高是-1, 右边高是1。左右高度相等则是0

2. AVL树节点的定义

template<class T>
struct AVLTreeNode {
public:explicit AVLTreeNode(const T& data): _left(nullptr), _right(nullptr), _parent(nullptr), _bf(0){}AVLTreeNode<T>* _left;AVLTreeNode<T>* _right;AVLTreeNode<T>* _parent;T _data;int _bf;
};

3. AVL树的插入

AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树其实还是一棵二叉搜索树。AVL树的插入分为两步:

  1. 按照二叉搜索树的方式插入新节点
  2. 调整节点的平衡因子

cur 插入后,parent的平衡因子一定要调整,在插入之前parent的平衡因子分为三种情况:0, -1, 1。

分为以下两种情况:

  1. 如果cur插入到parent的左侧,parent的平衡因子-1
  2. 如果cur插入到parent的右侧,parent的平衡因子+1

这个时候parent的平衡因子分为三种情况:

  1. 如果parent的平衡因子是0, 说明插入之前的平衡因子是正负1 插入成功
  2. 如果parent的平衡因子是正负1, 说明插入之前是0, 插入后更新为正负1,此时以parent为根的树的高度增加,需要继续向上更新
  3. 如果parent的平衡因子为正负2 , 则parent的平衡因子违反了平衡树的性质,需要对其进行旋转

4. AVL树的旋转

根据节点位置的不同,AVL树的旋转分为四种:

  1. 新节点插入较高左子树的左侧:右单旋

9590m6fllq-1688799146290.png

void rotateR(Node* parent) {Node* subL = parent->_left;Node* subLR = subL->_right;// 双亲的左为双亲左孩子的右孩子parent->_left = subLR;if (subLR) {subLR->_parent = parent;}subL->_right = parent;// 如果parent为子树Node* pParent = parent->_parent;parent->_parent = subL;subL->_parent = pParent;if (pParent == nullptr) {_root = subL;subL->_parent = nullptr;} else {// 如果parent是一个子树if (parent->_right == parent) {parent->_right = subL;} else {parent->_left = subL;}subL->_parent = pParent;}pParent->_bf = subL->_bf = 0;
}
  1. 新节点插入较高右子树的右侧:左单旋

99sk1rtx0s-1688800616297.png

void rotateL(Node* parent) {Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL) {subRL->_parent = parent;}subR->_left = parent;Node* pParent = parent->_parent;parent->_parent = subR;if (pParent == nullptr) {_root = subR;subR->_parent = nullptr;} else {if (pParent->_left == subR) {pParent->_left = subR;} else {pParent->_right = subR;}subR->_parent = pParent;}
}
  1. 新节点插入较高左子树的右侧:先左单旋再右单旋
ijtusg37n5-1688801355289.png
void rotateLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == 1){parent->_bf = 0;subLR->_bf = 0;subL->_bf = -1;}else if (bf == -1){parent->_bf = 1;subLR->_bf = 0;subL->_bf = 0;}else if (bf == 0){parent->_bf = 0;subLR->_bf = 0;subL->_bf = 0;}else{assert(false);}
}

左单旋是指将一个节点的右子树提升为根节点,同时将原根节点降为左子树的右子节点。右单旋则是将一个节点的左子树提升为根节点,同时将原根节点降为右子树的左子节点

判断应该使用左单旋还是右单旋,需要根据具体的情况来确定。一般来说,当某个节点的左子树高度大于右子树高度时,需要进行右单旋;当某个节点的右子树高度大于左子树高度时,需要进行左单旋。这是因为旋转操作可以通过改变树的结构来使得树重新平衡,使得左右子树的高度差保持在可接受的范围内。

  1. 新节点插入较高右子树的左侧:先右单旋再左单旋
vht2z75anc-1688802196294.png
void rotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 1){subR->_bf = 0;parent->_bf = -1;subRL->_bf = 0;}else if (bf == -1){subR->_bf = 1;parent->_bf = 0;subRL->_bf = 0;}else if (bf == 0){subR->_bf = 0;parent->_bf = 0;subRL->_bf = 0;}else{assert(false);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【面试题28】什么是PHP-FPM?它与PHP和Nginx有什么关系

文章目录 一、前言二、什么是PHP-FPM&#xff1f;三、PHP-FPM的生命周期3.1 启动阶段3.2 初始化阶段3.3 请求处理阶段3.4 关闭阶段 四、PHP-FPM与PHP的关系五、PHP-FPM与Nginx的通信方式六、总结 一、前言 本文已收录于PHP全栈系列专栏&#xff1a;PHP面试专区。 计划将全覆盖P…

华为战略方法论:BLM模型之战略意图(限制版)

目录 前言 案例 BLM模型 专栏列表 CSDN学院 个人简介 前言 对于任何一家企业来说&#xff0c;即便你没有清晰的战略规划。 一般也都是会有战略意图的。 战略意图具体是指你主观想要达成什么样的期望或者是状态。 换句话说&#xff0c;如果没有这种期望&#xff0c;你…

【云存储】主流分布式文件系统介绍

目录 1、引言 2、云存储与分布式文件系统 2.1、云存储 2.2、分布式文件系统 3、Google的三大云计算与云存储论文 3.1、The Google File System&#xff08;谷歌文件系统&#xff09; 3.2、MapReduce&#xff1a;Simplified Data Processing on Large Clusters&#xff0…

分类模型评估指标详解(二分类、多分类、混淆矩阵)

一 、二分类评估 1.混淆矩阵 (ConfusionMatrix) TP&#xff1a;1的预测为1 (正确的积极) 正确判断 FP&#xff1a;0预测为1 (错误的积极) 错误判断 FN&#xff1a;1预测为0 (正确的消极) 漏判断的 TN&#xff1a;0预测为0 (错误的消极) 成功未判断的 准确率&#xff1a;(a…

个人云服务器搭建MQTT服务器

个人云服务器搭建MQTT服务器 文章目录 个人云服务器搭建MQTT服务器1️⃣ 前言2️⃣ EMQX部署 1️⃣ 前言 MQTT &#x1f449;MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;即消息队列遥测传输协议 • 是一个轻量的发布订阅模式消息传输协议&#xff0c;专门…

STM32 Proteus仿真LCD12864俄罗斯方块-FZ0063

STM32 Proteus仿真LCD12864俄罗斯方块-FZ0063 Proteus仿真小实验&#xff1a; STM32 Proteus仿真LCD12864俄罗斯方块-FZ0063 功能&#xff1a; 硬件组成&#xff1a;STM32F103R6单片机 LCD12864显示器多个按键 1.标准俄罗斯方块经典游戏玩法&#xff0c;带计时&#xff0c…

Mysql 实现批量插入对已存在数据忽略或更新

Mysql 实现批量插入对已存在数据忽略/更新 文章目录 Mysql 实现批量插入对已存在数据忽略/更新一. 表的准备二. 实现2.1 实现原理2.2 批量插入对已存在数据忽略 一. 表的准备 CREATE TABLE demo (id int NOT NULL AUTO_INCREMENT COMMENT 主键id,name varchar(10) DEFAULT NUL…

shell脚本--------shell变量、条件表达式、流程控制

第三阶段基础 时 间&#xff1a;2023年7月7日 参加人&#xff1a;全班人员 内 容&#xff1a; shell变量、条件表达式、流程控制 目录 一、shell变量 二、shell条件表达式与运算符 三、break和continue语句 演示&#xff1a;break语句 continue语句 四、实例拓展 …

9.2.4 vim 的暂存盘、救援回复与打开时的警告讯息

当我们在使用 vim 编辑时&#xff0c; vim 会在与被编辑的文件的目录下&#xff0c;再创建一个名为.filename.swp 的文件。 比如说我们在上一个小节谈到的编辑 /tmp/vitest/man_db.conf 这个文件时&#xff0c; vim 会主动的创建 /tmp/vitest/.man_db.conf.swp 的暂存盘&#x…

常用数据分类算法原理介绍、优缺点分析与代码实现[LR/RF/DT/SVM/NavieBayes/GBDT/XGBoost/DNN/LightGBM等]

本文的主要目的是总结记录日常学习工作中常用到的一些数据分类算法&#xff0c;对其原理简单总结记录&#xff0c;同时分析对应的优缺点&#xff0c;以后需要的时候可以直接翻看&#xff0c;避免每次都要查询浪费时间&#xff0c;欢迎补充。 机器学习领域中常用的分类模型包括以…

智能物流监控系统的数据平台技术研究

完整资料进入【数字空间】查看——baidu搜索"writebug" 1.1 项目背景 物联网技术是利用传感器嵌入各种末端设备&#xff0c;通过无线或有线网络接入互联网以实现人与物、物与物实时互联的新兴技术[1]。 智能物流监控系统是在物流量越来越大、物流价值越来越贵重的背…

关于SpringBoot、Nginx 请求参数包含 [] 特殊符号 返回400状态

问题来源&#xff1a; 使用RESTful风格发送带有特殊符号(如&#xff1a;点、大括号等)的请求&#xff0c;当使用Nginx做地址映射时会返回报"HTTP Status 400-Bad Request"的错误&#xff0c;这个时候我们需要对Nginx的映射方式做一下调整。 Nginx调整完发现跳转后又报…