C++进阶之AVL树
个人主页:点我进入主页
专栏分类:C语言初阶 C语言进阶 数据结构初阶 Linux C++初阶 C++进阶 算法
欢迎大家点赞,评论,收藏。
一起努力,一起奔赴大厂
目录
一.前言
二.插入
三.旋转
3.1右旋
3.2左旋
3.3左右双旋
3.4右左双旋
四.测试
一.前言
在看这篇博客之前需要了解二叉搜索树的相关内容,可以看这篇博客二叉搜索树,AVL树可以看成为了解决二叉搜索树的问题,它保证了左右子树高度差不超过1。本次的内容的重点就是对AVL树的旋转。
二.插入
AVL树的插入规则和二叉搜索树的插入规则类似,左子树都小于父节点,右子树都大于父节点,在这里我们引入了一个平衡因子,我们先插入后然后进行调节平衡因子,平衡因子的计算=右子树的高度-左子树的高度,插入的新节点的平衡因子为0,当插入的节点在父节点的右边,父节点的平衡因子+1,当插入的节点在父节点的左边,父节点的平衡因子-1,当整后父节点的平衡因子为0时直接结束,不需要继续调整,当调整后父节点的平衡因子为+1或者-1时需要继续向上进行调整,当调整后父节点的平衡因子为+2或-2时需要进行旋转。我们看下面的代码实现:
bool insert(const pair<K, V>& kv)
{Node* newnode = new Node(kv);if (_root == nullptr) _root = newnode;else{Node* cur = _root, * parent = nullptr;while (cur){if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}else if (kv.first > cur->_kv.first) {parent = cur;cur = cur->_right;}else return false;}if (kv.first < parent->_kv.first) parent->_left = newnode;else parent->_right = newnode;newnode->_parent = parent;//调整平衡因子while (parent){if (newnode == parent->_left) parent->_bf--;else parent->_bf++;if (parent->_bf == 0) break;else if (parent->_bf == 1 || parent->_bf == -1){newnode = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){if (parent->_bf == 2 && newnode->_bf == 1){RatoteL(parent);}else if (parent->_bf == -2 && newnode->_bf == -1){RatoteR(parent);}else if (parent->_bf == 2 && newnode->_bf == -1){RatoteRL(parent);}else if (parent->_bf == -2 && newnode->_bf == 1){RatoteLR(parent);}else{assert(false);}break;}else{assert(false);}}}return true;
}
三.旋转
旋转有4种方式:向右旋转,向左旋转,左右双旋,右左双旋这四种
3.1右旋
看下面的抽象图

当n=0时全图为

当n=1时全图为

当n=2时我们有3种,但是在a的位置能放第3种,因为别的会自动进行旋转,b和c这三种都可以

当n=3时就会更多,所以这是列举不完的,针对右旋我们以下面这张图为例:

我们经过右旋后转化成下面的样子,针对的主要就是这几个节点
在旋转的过程中需要注意的是,parent节点是不是根节点,注意调整后subL节点的的父节点的调整,还有一点就是subLR是否为空节点,调整后需要将subL节点和parent节点的bf值改为0,我们看下面的代码:
void RatoteR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;subL->_right = parent;parent->_left = subLR;Node* ppNode = parent->_parent;subL->_parent = parent->_parent;parent->_parent = subL;if (subLR)subLR->_parent = parent;if (parent == _root){_root = subL;}else{if (ppNode->_left == parent)ppNode->_left = subL;elseppNode->_right = subL;}subL->_bf = parent->_bf = 0;}
3.2左旋
左旋的代码和右旋的类似,不过需要调节的平衡因子为2和1,我们看下面的图片

我们直接上代码:
void RatoteL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* ppNode = parent->_parent;parent->_parent = subR;subR->_left = parent;subR->_parent = ppNode;if (parent == _root){_root = subR;}else{if (ppNode->_left == parent)ppNode->_left = subR;elseppNode->_right = subR;}subR->_bf = parent->_bf = 0;
}
void RatoteRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RatoteR(subR);RatoteL(parent);if (bf == 1){parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;}}
3.3左右双旋
左右双旋的图片可以看为下面的抽象图:

当我们在b位置插入后再旋转,可以得到:

当我们插入到c位置后再经过旋转,可以得到:

当只旋转一次就会做一次镜像旋转,我们先让subL节点左旋,然后让parent右旋,然后进行调节平衡因子,我们看代码:
void RatoteLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RatoteL(subL);RatoteR(parent);if (bf == 1){subL->_bf = -1;}else if (bf == -1){parent->_bf = 1;}
}
3.4右左双旋
这个和左右双旋类似,我们直接看代码:
void RatoteRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RatoteR(subR);RatoteL(parent);if (bf == 1){parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;}}
四.测试
我们直接上代码:
public: void InOrder(){_InOrder(_root);}bool IsBalance(){return _IsBalance(_root);}
private:void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << "->" << root->_kv.second << endl;int left = _height(root->_left);int right = _height(root->_right);int sub = abs(left - right);cout << "bf-> " << sub<<endl;if (sub >= 2) cout<<"key-> "<< root->_kv.first << endl;_InOrder(root->_right);}int _height(Node* root){if (root == nullptr)return 0;int x = 1 + _height(root->_left);int y = 1 + _height(root->_right);return max(x , y);}bool _IsBalance(Node* root){ if (root == nullptr) return true;int left = _height(root->_left);int right = _height(root->_right);if (abs(right - left) >= 2){return false;}return _IsBalance(root->_left) && _IsBalance(root->_right);}
测试代码:
int main()
{srand(0);AVLTree<int, int> a;vector<int> v;for (int i = 0; i < 1000000; i++){int num = rand() + i;v.push_back(num);}cout << a.IsBalance() << endl;return 0;
}
运行可以看到:

相关文章:
C++进阶之AVL树
个人主页:点我进入主页 专栏分类:C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 C进阶 算法 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂 目录 一.前言 二.插入 三.旋转 3.1右旋 …...
sizeof 和 strlen 比较
sizeof 和 strlen 在 C 语言中都是用于获取某种“大小”的,但它们之间有着显著的区别。 sizeof sizeof 是一个运算符,用于计算数据类型或对象在内存中的大小(以字节为单位)。它可以在编译时确定结果,因为它计算的是类…...
音视频开发—FFmpeg 打开摄像头进行RTMP推流
实验平台:Ubuntu20.04 摄像头:普通USB摄像头,输出格式为YUV422 1.配置RTMP服务器推流平台 使用Nginx 配置1935端口即可,贴上教程地址 ubuntu20.04搭建Nginxrtmp服务器) 2.配置FFmpeg开发环境 过程较为简单,这里不…...
D触发器(D Flip-Flop)与D锁存器(D Latch)
1 基础概念 我们先来简单回顾一下D触发器(D flip-flop)和D锁存器(D latch)的概念,以及它们在数字电路中的作用。 1.1 D触发器(D Flip-Flop) D触发器是一种数字存储器件,它在时钟信号…...
JDK19特性
JDK19特性 一、JAVA19概述 JDK 19 2022 年 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。 JDK 19 只有 7 个新特性: JEP 405: Record Patterns(记录模式)[1] (预览)JEP 422: Linux/RISC-V Port[2]JEP 424: Foreign …...
sql语句中常用的函数有那些
1、字符串函数 CONCAT(string1, string2, ...): 连接两个或多个字符串。 UPPER(string): 将字符串转换为大写。 LOWER(string): 将字符串转换为小写。 TRIM(string): 去除字符串两端的空格。 LENGTH(string): 返回字符串的长度。 SUBSTRING(string, start, length): 从字符串中…...
odoo17 小变更3 Warning、 “attrs “和 “states “不再用
odoo17 小变更 1、Warning from odoo.exceptions import ValidationError,Warning ImportError: cannot import name Warning from odoo.exceptions (D:\od172406\odoo\exceptions.py) 2、自 17.0 版起,不再使用 "attrs "和 "states "属性。 …...
Unity3d 游戏暂停(timeScale=0)引起的deltaTime关联的系列问题解决
问题描述 游戏暂停的功能是通过设置timeScale0实现的,不过在暂停游戏的时候,需要对角色进行预览和设置,为了实现这个功能,是通过鼠标控制相机的操作,为了使相机的操作丝滑,获取鼠标操作系数乘以Time.delta…...
服务端代码编写中MySql大小写在Java中报错问题解决
报错信息: 原因:MySql和Java变量大小写产生的冲突。 经过查阅各个博客等,得出浅显结论(不一定对):MySql大小写不敏感,Java大小写敏感,当Javabean转为MySql数据库表时,Ja…...
CRMEB 多店商品详情页装修说明
一、功能介绍 商家可调整商品详情各板块样式,可根据不同的需求开启或关闭单独的板块 二、操作流程 装修 > 商品详情 三、功能说明 1、商品信息 可控制商品详情页面商品信息的显示与隐藏 2、会员信息,排行榜 控制商品详情页面会员信息及排行榜的…...
Redis-使用 jedis 操作数据
文章目录 1、Jedis简介2、环境准备3、创建maven普通项目,导入如下依赖4、测试JAVA程序和Redis之间的通信 1、Jedis简介 "Jedis" 通常是作为 "Java Redis" 的缩写或简称来理解的。Java Embedded Data Structures Interface 表示 Java嵌入式数据结构接口 2、…...
简说PIP换源
概述 PIP(Python Package Installer)是 Python 的包管理工具,用于安装和管理 Python 包。默认情况下,PIP 从 Python 官方的包仓库(即 PyPI)下载和安装包。然而,由于网络原因,访问官…...
django学习入门系列之第三点《CSS基础样式介绍2》
文章目录 文字对齐方式外边距内边距往期回顾 文字对齐方式 水平对齐方式 text-align: center;垂直对齐方式 /* 注意,这个只能是一行来居中 */ line-height:/*长度*/ ;样例 <!DOCTYPE html> <html lang"en"> <head><meta charset…...
分布式光纤测温DTS在工程现场中稳定性与可靠性如何?
20年前,分布式光纤测温(Distributed Temperature Sensing,DTS)技术的发展尚不成熟,设备成本高昂,其稳定性与可靠性也存在一定问题。然而,经过二十多年的不断发展与创新,DTS技术在工程现场应用中取得了显著进…...
PHP多线程模块parallel的编译安装和多线程编程演示
从PHP7开始,多线程编原有的pthreads已经不在维护,而是使用parallel替代。 由于是新的模块,样例代码很少,这里总结一个简单的代码和详细的备注供大家参考。 编译和安装 parallel需要启用ZTS(Zend Thread Safety&…...
记录grid布局属性
grid布局 分为容器和项目元素 容器属性 #container{display:grid;grid-template-columns:100px 100px 100px;/* 1fr 表示比例为占1份 */grid-template-columns:1fr 100px 1fr;/*100px为1列,自动填充,容器宽度不足则换行*/grid-template-columns:repeat(auto-fill,100px);/* …...
12.爬虫---PyMysql安装与使用
12.PyMysql安装与使用 1.安装 PyMySQL2.使用PyMySQL2.1创建数据表2.2连接数据库2.3增加数据2.4修改数据2.5查询数据2.6删除数据2.7关闭连接 3.总结 MySQL 安装可以看这篇文章MySql 安装与使用(非常详细) 1.安装 PyMySQL PyMySQL是Python中用于连接MySQL…...
VS2022遇到的两个问题
问题一:找不到定义的头文件 别的博主说是:在属性页里面进行改写,改成是,我试过之后并不行; 解决思路:但其实在右边视图里面找到你自己定义的头文件加到你运行文件中就行;因为程序就只有一个入口…...
【Android14 ShellTransitions】(六)SyncGroup完成
这一节的内容在WMCore中,回想我们的场景,是在Launcher启动某一个App,那么参与动画的就是该App对应Task(OPEN),以及Launcher App对应的Task(TO_BACK)。在确定了动画的参与者后&#x…...
技术管理转型之战:决策之道-管理中的智慧与策略
文章目录 引言一、决策的重要性二、常见的决策方式1. 理性决策(Rational Decision Making)2. 有限理性(Bounded Rationality)3. 直觉决策(Intuitive Decision Making)4. 循证管理(Evidence-Base…...
Excel报表自动化:用JXLS实现动态数据填充的5个高级技巧
Excel报表自动化:用JXLS实现动态数据填充的5个高级技巧 每次看到同事手动复制粘贴数据到Excel模板时,我都忍不住想分享JXLS这个神器。作为Java开发者,我们完全可以用代码实现专业级报表自动化,告别重复劳动。本文将带你深入JXLS的…...
TwinCAT3进阶指南:台达A2伺服扭矩读取与回零实战
1. TwinCAT3与台达A2伺服的基础配置 在开始扭矩读取和回零操作之前,我们需要先完成TwinCAT3与台达A2伺服的基础配置。这部分工作看似简单,但却是后续所有高级功能的基础。我遇到过不少开发者因为基础配置没做好,导致后面各种奇怪的问题。 首先…...
从WordPress同步到数据库:一个真实案例拆解n8n节点间的“数据对话”
从WordPress到数据库:用n8n构建数据管道的实战解剖 当你点击WordPress后台的"发布"按钮时,一篇新文章如何穿越数字世界,精准落入目标数据库的表格中?这背后是一场由n8n节点编排的精密数据芭蕾。本文将带你走进一个真实的…...
Windows 11性能优化指南:让系统重获新生的实用工具
Windows 11性能优化指南:让系统重获新生的实用工具 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本,用于从Windows中移除预装的无用软件,禁用遥测,从Windows搜索中移除Bing,以及执行各种其他更改以简化和改善…...
实战:基于Local Path Provisioner与Helm的RustFS云原生存储部署详解
1. RustFS与云原生存储架构解析 第一次接触RustFS是在去年帮客户设计对象存储方案时,当时被它用Rust语言实现的内存安全特性吸引。作为一款兼容S3协议的开源分布式存储系统,RustFS在性能测试中表现出色——单节点吞吐量能达到1.2GB/s,延迟控制…...
告别纯理论:用OAI 5G开源平台+USRP B210硬件,实测端到端5G SA数据业务
从零构建5G SA实验环境:OAI开源平台与USRP B210实战指南 当5G技术从实验室走向商业化应用时,许多开发者面临一个尴尬的现实:理论知识与实际操作之间存在巨大鸿沟。本文将带你跨越这道鸿沟,使用OAI开源平台和USRP B210软件定义无线…...
BEYOND REALITY Z-Image实测:同一张脸,两种质感,细节对比一目了然
BEYOND REALITY Z-Image实测:同一张脸,两种质感,细节对比一目了然 今天我要带大家做一个有趣的实验。想象一下,你面前站着同一个人,但左边是手机快照,右边是专业单反拍摄的照片——这就是BEYOND REALITY Z…...
LinkSwift网盘直链下载助手:2025年高效下载终极解决方案
LinkSwift网盘直链下载助手:2025年高效下载终极解决方案 【免费下载链接】Online-disk-direct-link-download-assistant 可以获取网盘文件真实下载地址。基于【网盘直链下载助手】修改(改自6.1.4版本) ,自用,去推广&am…...
如何让AI帮你读完100篇文献,并写出综述的核心内容?
对于每一位科研工作者而言,面对一个新的课题或研究方向,最让人望而生畏的往往不是实验本身,而是前期那如山般堆积的文献调研。当你需要在短时间内读完100篇甚至更多核心文献,并从中提炼出逻辑严密、观点独到的综述核心内容时&…...
COMSOL声子晶体复能带模型与PDE模块:声学黑洞复能带模型及实虚能带绘制与二维结构分析
comsol声子晶体复能带模型 PDE模块 声学黑洞 复能带模型 实能带与虚能带的绘制 参考论文 前两个是论文图,后四个是模型及结果图。 可根据模型设置,进行其他二维结构的分析复能带这玩意儿搞声子晶体的肯定不陌生,但用COMSOL PDE模块手搓模型…...
