从零开始的C++(十八)

avl树中insert的模拟实现

avl树特点:

1.是搜索二叉树

2.每个结点的左右子树高度差的绝对值不超过2

inser模拟实现:

	// 右单旋void RotateR(Node* pParent){Node* parent = pParent;Node* pr = parent->_pRight;Node* prl = pr->_pLeft;//记录父节点Node* pp = parent->_pParent;//更新指针parent->_pRight = prl;if(prl)//判断prl是否存在prl->_pParent = parent;pr->_pLeft = parent;parent->_pParent = pr;if (pp == nullptr){//若parent是根节点_pRoot = pr;pr->_pParent = nullptr;}else{   //父节点连接if (pp->_data < parent->_data){pp->_pRight = pr;pr->_pParent = pp;}else{pp->_pLeft = pr;pr->_pParent = pp;}}//更新平衡因子parent->_bf = 0;pr->_bf = 0;}// 左单旋void RotateL(Node* pParent){Node* parent = pParent;Node* pl = parent->_pLeft;Node* plr = pl->_pRight;//记录父节点Node* pp = parent->_pParent;//更新指针parent->_pLeft = plr;if (plr)//判断prl是否存在plr->_pParent = parent;pl->_pRight = parent;parent->_pParent = pl;if (pp == nullptr){//若parent是根节点_pRoot = pl;pl->_pParent = nullptr;}else{   //父节点连接if (pp->_data < parent->_data){pp->_pRight = pl;pl->_pParent = pp;}else{pp->_pLeft = pl;pl->_pParent = pp;}}//更新平衡因子parent->_bf = 0;pl->_bf = 0;}// 右左双旋void RotateRL(Node* pParent){  Node* parent = pParent;Node* pr = parent->_pRight;Node* prl = pr->_pLeft;int bf = prl->_bf;RotateL(pParent->_pRight);RotateR(pParent);//更新平衡因子if (bf == 0){parent->_bf = pr->_bf = prl->_bf = 0;}else{parent->_bf = -1;pr->_bf = prl->_bf = 0;}}// 左右双旋void RotateLR(Node* pParent){Node* parent = pParent;Node* pl= parent->_pLeft;Node* plr = pl->_pRight;int bf = plr->_bf;RotateR(pParent->_pLeft);RotateL(pParent);//更新平衡因子if (bf == 0){parent->_bf = pl->_bf = plr->_bf = 0;}else{parent->_bf = 0;pl->_bf = 1;plr->_bf = 0;}}// 在AVL树中插入值为data的节点bool Insert(const T& data){if (_pRoot == nullptr){_pRoot = new Node(data);return true;}Node* cur = _pRoot;Node* parent = nullptr;//查看插入位置while (cur){if (cur->_data < data){   parent = cur;cur = cur->_pRight;}else if (cur->_data > data){  parent = cur;cur = cur->_pLeft;}else{//有重复值,插入失败return false;}}//此时parent的子树就是存放data的结点if (parent->_data < data){cur = new Node(data);parent->_pRight = cur;cur->_pParent = parent;parent->_bf++;}else{cur = new Node(data);parent->_pLeft = cur;cur->_pParent = parent;parent->_bf--;}//开始旋转while (parent){if (parent->_bf == 0){//代表插入前后高度不变break;}else if (parent->_bf == 1 || parent->_bf == -1){//插入后高度改变,但仍保持平衡条件cur = parent;parent = parent->_pParent;if (parent == nullptr){break;}if (cur == parent->_pLeft){parent->_bf--;}else{parent->_bf++;}}else if (parent->_bf == 2 || parent->_bf == -2){//此时不满足平衡条件,需要旋转//旋转分四种情况//1.右右if(parent->_bf==2&&cur->_bf==1)RotateR(parent);//2。左左else if(parent->_bf == -2 && cur->_bf == -1)RotateL(parent);//3.右左else if(parent->_bf == 2 && cur->_bf == -1)RotateRL(parent);//4.左右else if(parent->_bf == -2 && cur->_bf == 1)RotateLR(parent);//旋转后高度和插入前高度相同,因此结束break;}else{//此时平衡因子异常,发出中断请求assert(false);}}}

对于一个结点的插入,其影响其父节点的平衡因子(_bf)的值,因此每次插入都需要修改其父节点的平衡因子,而父节点的平衡因子的修改又可能会影响父节点的父节点的平衡因子的值,因此可能会出现连锁修改的情况。以下是所有可能的情况:

1.插入结点后父节点的平衡因子的值变为0,在该情况下父节点的高度在插入前后未发生改变,因此不会继续影响父节点的父节点,因此可以直接退出循环。

2.插入结点后父节点的平衡因子的值变为1或-1,在该情况下父节点的高度插入前后发生修改,增加1,此处通过判断父节点是其父节点的左右子树,来影响父节点的父节点的平衡因子,并继续进入循环进行判断。

3。插入后父节点平衡因子变成大于2的情况,此时抛出异常,因为父节点的平衡因子应符合不超过2,即使在插入新节点后,其平衡因子最大只能增加1,最小只能减小1,因此只能变成绝对值小于等于2的情况,不应该出现绝对值大于2的情况。

3.插入结点后父节点平衡因子变成2或-2,此时不在符合平衡因子绝对值不超过2的情况,因此需要对以父节点为根结点的子树进行旋转修改。此时又分成四种情况。

情况1:

对于这种情况,只需要进行一次选择即可,旋转后的结果如下图:

具体实现逻辑就是parent变成其右孩子的左孩子,原本右孩子的左孩子变成parent的右孩子

经过旋转,使得当前的二叉树仍是avl树,其旋转后的高度与插入结点之前的高度一致,因此不需要继续向上修改父节点。

情况2:

此时若只以A为根进行旋转,则旋转后仍有平衡因子为2或-2的情况,因此需要进行两次旋转。为方便理解,上图等价于下图,以下图来分析。

具体思路:先以b为根进行旋转,使得旋转后高度更高的结点在右侧。

然后以A为根进行旋转即可。

经过两次旋转,实现了高度缩减一,且和插入结点之前相比,子树的父节点的平衡因子不用改变,因此也不需要继续进入循环。

对于上述两种情况,存在镜像的情况,对于那两种情况,只需要与对应的将左右旋转、子树旋转等改变即可。

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

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

相关文章

红海营销时代,内容占位的出海品牌更有机会营销占位

#01 品牌出海&#xff1a;内容占位就是品牌营销占位 红海营销时代&#xff0c;内容信息充斥着用户周边。无论线上还是线下&#xff0c;生活工作、休闲娱乐等不同场景内&#xff0c;广告信息均无孔不入。对于用户来说&#xff0c;能记住的品牌或者商品往往寥寥无几。 占位营销…

全网好评!12个网络工程师必备工具!

你们好&#xff0c;我的网工朋友。 今天来一期久违的工具推荐。工欲善其事必先利其器&#xff0c;好的工具势必会让网工们如虎添翼。 快速掌握正确的工具&#xff0c;意味着你可以轻松地完成复杂的工作。 但市面上的软件太多了&#xff0c;到底选用哪个工具&#xff0c;这还…

【最新Tomcat】IntelliJ IDEA通用配置Tomcat教程(超详细)

前言 IntelliJ IDEA是一个强大的集成开发环境&#xff0c;能够大大简化Java应用程序的开发和部署过程。而Tomcat作为一个流行的Java Web服务器&#xff0c;其与IntelliJ IDEA的整合能够提供便捷的开发环境&#xff0c;让开发人员更专注于代码的创作与优化。 在配置IntelliJ IDE…

linux在非联网、无网络环境下,使用yumdownload、reportrack方法安装rpm包

文章目录 前言1、下载yum-utils​​2、yumdownloader3、repotrack4、安装5、yumdownloader和repotrack的区别总结 前言 当开发者在联网环境下使用Linux时&#xff0c;可以轻松地通过yum或apt-get安装软件。然而&#xff0c;在公司和企业中&#xff0c;由于安全原因&#xff0c…

执行npm的时候报权限问题的解决方案

我们在执行npm操作的过程中&#xff0c;会出现以下权限问题&#xff0c;解决方案: 管理员身份 运行cmd 切换目录到要执行命令的文件下 再进行npm操作即可

java17 linux 环境配置

linux版本 :centos 8 1.能联网的情况下: wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 2.mkdir /usr/local/java tar zxvf jdk-17_linux-x64_bin.tar.gz -C /usr/local/java 3./etc/profile增加: export JAVA_HOME/usr/local/java/jdk-17.…

社交媒体驱动的独立站流量增长:YouTube引流技巧

随着互联网的不断发展&#xff0c;视频内容在网上变得越来越受欢迎。YouTube作为世界上最大的视频分享平台之一&#xff0c;成为了吸引流量和观众的理想场所。对于跨境卖家来说&#xff0c;利用YouTube来增加独立站流量是一种有效的策略&#xff0c;可以增加知名度、吸引潜在客…

IDEA创建SpringBoot的多模块项目教程

最近在写一个多模块的SpringBoot项目&#xff0c;基于过程总了一些总结&#xff0c;故把SpringBoot多个模块的项目创建记录下来。 首先&#xff0c;先建立一个父工程&#xff1a; &#xff08;1&#xff09;在IDEA工具栏选择File->New->Project &#xff08;2&#xff0…

hypermesh学习总结(一)

1、hypermesh导入导出 2、hypermesh如何使用拓扑命令&#xff0c;连接多个几何体为一个&#xff1f; 3、hypermesh模式选择 分别有显示动力学模式explicit,标准模式Standard3D(静力学及模态等) 4、检查网格单元质量 5、基本平移旋转显示视角操作 6、更改网格划分最小…

二-内存模型及所有权和引用、借用

1. 内存模型1 内存模型&#xff0c;heap和stack的区别&#xff0c;GC方面和go的区别 基本同go一样&#xff0c;分为堆内存、栈内存。栈内存函数退出时会自动释放&#xff0c;大小有限&#xff0c;一般是比较“小”的变量存到栈上。 比较“大”的或者大小动态变化的会分配到堆上…

vue3 ref和reactive使用watch属性的方法和区别

在Vue 3中&#xff0c;您可以使用watch函数和watch选项来监视ref和reactive创建的响应式数据的变化。下面是它们的使用方法和区别&#xff1a; 使用方法&#xff1a; 使用ref和watch&#xff1a; import { ref, watch } from vue;const count ref(0);watch(count, (newVal,…

【算法挨揍日记】day28——413. 等差数列划分、978. 最长湍流子数组

413. 等差数列划分 413. 等差数列划分 题目描述&#xff1a; 如果一个数列 至少有三个元素 &#xff0c;并且任意两个相邻元素之差相同&#xff0c;则称该数列为等差数列。 例如&#xff0c;[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。 给你一个整数数组 nums…

【数据结构】邻接表与邻接矩阵的转换

一.基本思想 1.邻接矩阵转换为邻接表&#xff1a; 先设置一个空的邻接表&#xff0c;然后查找邻接矩阵的值不为零元素&#xff0c;找到后在邻接表的单链表对应位置加入表边节点。 2.邻接表转换为邻接矩阵&#xff1a; 在邻接表上顺序取出每个表边结点&#xff0c;将邻接矩阵…

【基础架构】part-1 高可用策略和知识点总结

​ 系统应该保持高可用性&#xff0c;以确保用户能够始终访问和使用系统。这可以通过设计冗余和容错机制来实现&#xff0c;如负载均衡、故障转移、备份和恢复策略等。 1.1、引入冗余 通过冗余架构设计&#xff0c;如使用多个服务器节点、多个数据中心或云区域&#xff0c;确…

gRPC博客【建设进度0%】

学习资料来源&#xff1a;https://grpc.io/

鸿蒙系统调研适配

写在前面&#xff1a; 以下内容基于我个人翻阅的官方资料以及自己的理解写的&#xff0c;可能存在认知和理解上的偏差&#xff0c;有些地方并不一定是对的&#xff0c;请谨慎对待&#xff0c;注意甄别&#xff01; 一、鸿蒙OS是什么&#xff1f; 华为推出的多端统一平台&…

【Gateway】基于ruoyi-cloud-plus项目,gateway局部过滤器和过滤返回以及集成nacos

1.使用Gateway路由转发 1.1标题引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>1.2添加YML配置 spring:cloud:gateway:# 打印请求日志(自定义)…

链动2+1模式:创新营销引领白酒产业新潮流

在当今高度竞争的市场环境中&#xff0c;创新营销模式对于企业的发展至关重要。链动21模式作为一种独特的营销策略&#xff0c;将白酒产品与该模式相结合&#xff0c;充分发挥其优势&#xff0c;通过独特的身份晋升和奖励机制&#xff0c;快速建立销售渠道&#xff0c;提高用户…

C++基础从0到1入门编程(二)

系统学习C 方便自己日后复习&#xff0c;错误的地方希望积极指正 往期文章&#xff1a;C基础从0到1入门编程&#xff08;一&#xff09; 参考视频&#xff1a; 1.黑马程序员匠心之作|C教程从0到1入门编程,学习编程不再难 2.系统化学习C 1 函数指针和回调函数 如果把函数的地址…

【C语言.oj刷题】有序#整型矩阵元素查找##{思路+C源码}

目录 题目信息 题目分析&#xff1a; 法一&#xff1a; 遍历二维数组&#xff08;低效&#xff09; 思路 源码 局限性 法二&#xff1a; 对每一行二分查找&#xff08;有所提效&#xff09; 思路 源码 局限性 法三&#xff1a; 利用一切有利条件使用二分查找 思路 …