AVL树的删除方法简单实现

看过前面的AVL树的介绍和插入方法实现AVL树了解并简单实现-CSDN博客,接着可以来学习删除方法的实现

目录

1.AVL树的删除

2.平衡因子调节

3.删除代码逻辑

4.AVL树的整体代码


1.AVL树的删除

因为AVL树也是二叉搜索树,可按照二叉搜索树的方式将节点删除,然后再更新平衡因子,只不过与删除不同的时,删除节点后的平衡因子更新,最差情况下一直要调整到根节点的位置。

这里我们按照前面写过的二叉搜索树的删除的方法基础上进行AVL树的删除

  • 对与删除节点有两个孩子,找它右子树最左结点,进行替换,就能转化为删除节点只有一个孩子或0个孩子的情况

  • 删除节点有0个或1个孩子(这个我就不画图了,可以参考前面搜索二叉树删除画的图二叉搜索树了解和实现-CSDN博客)

现在最主要的是删除节点后,要进行调节平衡因子


2.平衡因子调节

(1)parent的平衡因子原来为0,在它的左子树或右子树被缩短后,则它的平衡因子改为1或-1。由于以 parent为根的子树高度没有改变,从parent到根结点的路径上所有结点都不需要调整。


(2)结点parent的平衡因子原不为0,且较高的子树被缩短,则parent的平衡因子变为0。以parent为根的子树高度减1,为此需要继续向上调整平衡因子。


(3)结点parent的平衡因子原为1/-1,且较矮的子树又被缩短,则在结点parent发生不平衡。为此需进行平衡化旋转来恢复平衡。

情况一:

情况一:通过一次单旋来恢复结点parent的平衡,由于旋转后以parent为根的子树的高度没有发生改变,此时就可不用再向上调整了。


情况二:

情况二:通过一次单旋来恢复结点parent的平衡,但由于旋转后以parent为根的子树的高度减一,此时就要再继续向上调整了。


情况三:

1)b==h-2,c==h-1,调整后的平衡因子:parent== -1,subRL=0,subR= 0

2)  b==h-1,c==h-1,调整后的平衡因子:parent== 0,subRL=0,subR= 0

3)  b==h-1,c==h-2,调整后的平衡因子:parent== 0,subRL=0,subR= 1

双旋后,这颗子树的高度减少了1,旋转完了还要继续向上调整平衡因子。

1)b==h-2,c==h-1,调整后的平衡因子:parent== 0,subRL=0,subR= -1

2)  b==h-1,c==h-1,调整后的平衡因子:parent== 0,subRL=0,subR= 0

3)  b==h-1,c==h-2,调整后的平衡因子:parent== 1,subRL=0,subR= 0

双旋后,这颗子树的高度减少了1,旋转完了还要继续向上调整平衡因子。


3.删除代码逻辑

bool erase(const K& key){Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < key){parent = cur;cur = cur->_right;}else if (cur->_kv.first > key){parent = cur;cur = cur->_left;}else // 找到结点进行删除{// 删除最右节点时,若最右节点父亲左为nullptr// 当删除最右结点后,最右结点父亲的右也为nullptr了,cur也为nullptr// 到时候判断cur为这个父结点的左还是右有问题,所以多加一个判断条件bool curIsParentLeft = false;Node* delNode = nullptr; // 处理要删除的结点// 0-1个孩子可以合在一起处理// 对于0个孩子的parent随便指向cur的左或右孩子// 对于1个孩子的,parent只能指向cur的左孩子或者右孩子if (cur->_left == nullptr) // (左孩子为空,右孩子不为空)||(左孩子和右孩子都为空)进入{if (parent == nullptr) // 要删除的结点为根结点 cur==_root{_root = cur->_right;}else{// 判断cur在parent的左还是右if (parent->_left == cur){parent->_left = cur->_right;curIsParentLeft = true;}else{parent->_right = cur->_right;curIsParentLeft = false;}}delNode = cur;cur = cur->_right;}else if (cur->_right == nullptr)// (左孩子不为空,右孩子为空)进入{if (parent == nullptr) // 要删除的结点为根结点 cur==_root{_root = cur->_left;}else{// 判断cur在parent的左还是右if (parent->_left == cur){parent->_left = cur->_left;curIsParentLeft = true;}else{parent->_right = cur->_left;curIsParentLeft = false;}}delNode = cur;cur = cur->_left;}else{// 2个孩子// 这里找右子树中最小的key替换Node* rightMinP = cur;Node* rightMin = cur->_right;while (rightMin->_left){rightMinP = rightMin;rightMin = rightMin->_left;}// 找到进行替换cur->_kv = rightMin->_kv;// 判断rightMin在rightMinP的左还是右if (rightMinP->_left == rightMin){// rightMin左孩子不可能有,右孩子有或没有rightMinP->_left = rightMin->_right;curIsParentLeft = true;}else{rightMinP->_right = rightMin->_right;curIsParentLeft = false;}delNode = rightMin;parent = rightMinP;cur = rightMin->_right;}_upAdjust(parent, cur, curIsParentLeft);delete delNode; // 删除return true;}}return false;}
void _upAdjust(Node* parent,Node* cur,bool curIsParentLeft){//继续向上调整while (parent != NULL){if (cur == parent->_left && curIsParentLeft){parent->_bf++;}else{parent->_bf--;}if (parent->_bf == 1 || parent->_bf == -1){// 删除后高度不变break;}else if (parent->_bf == 0){// 往上更新cur = parent;parent = parent->_parent;if (parent != nullptr){if (parent->_left == cur){curIsParentLeft = true;}else{curIsParentLeft = false;}}}else if (parent->_bf == 2 || parent->_bf == -2){if (parent->_bf == 2 && parent->_right->_bf == 0){// 左单旋_RotateL(parent);// 调整旋转后的平衡因子// 旋转后parent还是指向原来那个结点,只是位置换了parent->_bf = 1;parent->_parent->_bf = -1;// 旋转完了不需要往上更新平衡因子,旋转完后这课树原来高度==旋转高度break;}else if (parent->_bf == -2 && parent->_left->_bf == 0){// 右单旋_RotateR(parent);parent->_bf = -1;parent->_parent->_bf = 1;break;} // 剩下后面情况旋转后高度都变了(降低了1),所以要继续向上调整平衡因子else if (parent->_bf == 2 && parent->_right->_bf == 1){// 左单旋_RotateL(parent);parent->_bf = 0;parent->_parent->_bf = 0;// 继续向上调整平衡因子cur = parent->_parent;parent = cur->_parent;if (parent != nullptr){if (parent->_left == cur){curIsParentLeft = true;}else{curIsParentLeft = false;}}}else if (parent->_bf == -2 && parent->_left->_bf == -1){//右单旋_RotateR(parent);parent->_bf = 0;parent->_parent->_bf = 0;// 继续向上调整平衡因子cur = parent->_parent;parent = cur->_parent;if (parent != nullptr){if (parent->_left == cur){curIsParentLeft = true;}else{curIsParentLeft = false;}}}else if (parent->_bf == 2 && parent->_right->_bf == -1){// 右左双旋_RotateRL(parent);// 旋转完平衡因子修改和插入后平衡因子修改后的结果一样(这里不做修改了)// 继续向上调整平衡因子cur = parent->_parent;parent = cur->_parent;if (parent != nullptr){if (parent->_left == cur){curIsParentLeft = true;}else{curIsParentLeft = false;}}}else if (parent->_bf == -2 && parent->_left->_bf == 1){// 左右双旋_RotateLR(parent);// 旋转完平衡因子修改和插入后平衡因子修改后的结果一样(这里不做修改了)// 继续向上调整平衡因子cur = parent->_parent;parent = cur->_parent;if (parent != nullptr){if (parent->_left == cur){curIsParentLeft = true;}else{curIsParentLeft = false;}}}}else{// 前面出错了assert(false);}}}

4.AVL树的整体代码

AVL/AVL.h · wrf/C++test_cpp - Gitee.com


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

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

相关文章

ArcGIS的汉字(亚洲文本)垂直标注

01 需求说明 实现ArcGIS的汉字&#xff08;亚洲文本的垂直标注&#xff09;。 启用 Maplex 标注引擎。 在标注 工具条上单击标注管理器按钮 。 选中要进行标注的图层旁边的复选框。 选择图层下方的标注分类。 单击符号。 选中 CJK 字符方向复选框。 仅当字体有垂直的文本度…

飞凌嵌入式RK3576核心板已适配Android 14系统

在今年3月举办的RKDC2024大会上&#xff0c;飞凌嵌入式FET3576-C核心板作为瑞芯微RK3576处理器的行业首秀方案重磅亮相&#xff0c;并于今年6月率先量产发货&#xff0c;为客户持续稳定地供应&#xff0c;得到了众多合作伙伴的认可。 FET3576-C核心板此前已提供了Linux 6.1.57…

基于python的dlib库的人脸识别实现

1、环境搭建 基于dlib库的人脸识别环境配置需求如下: conda create -n dlibFace python3.6.4 conda activate dlibFacepip install dlib19.8.1 pip install opencv-python3.4.1.15 pip install tqdm 安装如下: 2、模块介绍 2.1 源代码下载 源代码点击:下载源代码 2.2 源码…

Ubuntu问题 -- 允许ssh使用root用户登陆

目的 新重装的系统, 普通用户可以使用ssh登陆服务器, 但是root不能使用ssh登陆 方法 vim 编辑ssh配置文件 sudo vim /etc/ssh/sshd_config找到 PermitRootLogin 这一行, 把后面值改成 yes 重启ssh sudo service sshd restart然后使用root账号登陆即可

DAY6 线程

作业1&#xff1a; 多线程实现文件拷贝&#xff0c;线程1拷贝一半&#xff0c;线程2拷贝另一半&#xff0c;主线程回收子线程资源。 代码&#xff1a; #include <myhead.h> sem_t sem1; void *copy1()//子线程1函数 拷贝前一半内容 {int fd1open("./1.txt",O…

第六十四周周报 TCN-LSTM

文章目录 week 64 TCN-LSTM摘要Abstract1. 题目2. Abstract3. 文献解读3.1 Introduction3.2 创新点 4. 网络结构4.1 数据分析4.2 混合深度学习框架的开发 5. 实验结果6.结论 week 64 TCN-LSTM 摘要 本周阅读了题为A hybrid deep learning approach to improve real-time effl…

单元测试时报错找不到@SpringBootConfiguration

找到问题出现原因&#xff1a; 错误表示 Spring Boot 在运行测试时无法找到 SpringBootConfiguration 注解。 通常&#xff0c;SpringBootTest注解用于加载 Spring Boot 应用上下文&#xff0c;但它需要找到一个带有SpringBootConfiguration&#xff08;或者Configuration&am…

【图像压缩感知】论文阅读:Content-Aware Scalable Deep Compressed Sensing

tips&#xff1a; 本文为个人阅读论文的笔记&#xff0c;仅作为学习记录所用。本文参考另一篇论文阅读笔记 Title&#xff1a; Content-Aware Scalable Deep Compressed Sensing Journal&#xff1a; TIP 2022 代码链接&#xff1a; https://github.com/Guaishou74851/CASNet…

浙大版《C语言程序设计(第4版)》题目集(一)

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

谷歌AI进军教育,这将改变未来?

近日&#xff0c;谷歌&#xff08;Google&#xff09;正式发布了一款名为“Learn About”的全新人工智能工具&#xff0c;这犹如一颗耀眼的新星&#xff0c;在教育领域掀起了一阵波澜。这款产品具有诸多令人瞩目的亮点&#xff0c;为学习者带来了全新的学习体验。 个性化的学习…

Python酷库之旅-第三方库Pandas(218)

目录 一、用法精讲 1021、pandas.DatetimeIndex.inferred_freq属性 1021-1、语法 1021-2、参数 1021-3、功能 1021-4、返回值 1021-5、说明 1021-6、用法 1021-6-1、数据准备 1021-6-2、代码示例 1021-6-3、结果输出 1022、pandas.DatetimeIndex.indexer_at_time方…

MATLAB用到的矩阵基础知识(矩阵的乘和矩阵的逆)

1. 矩阵乘法 方法: 设第一个矩阵为 A A A,第二个矩阵为 B B B,则 A A A的第一行乘 B B B的第一列,先想乘再相加,作为目标矩阵的一个元素。 前提条件: 所以我们可以看到矩阵相乘的前提条件:第一个矩阵的列数等于第二个矩阵的行数。否则,我们就无法进行行和列的相乘。 最…

SpringBoot+MyBatis+MySQL的Point实现范围查找

前言 最近做了一个功能&#xff0c;需要通过用户当前位置点获取指定范围内的数据。由于后端存储用的是 MySQL&#xff0c;故选择使用 MySQL 中的 Point 实现范围查找功能。ORM 框架用的是 MyBatis&#xff0c;MyBatis 原生并不支持 Point 字段与 POJO 的映射&#xff0c;需要自…

共享门店模式:创新零售的新篇章

​在消费升级和数字化转型的双重浪潮下&#xff0c;传统零售业正面临前所未有的挑战与机遇。其中&#xff0c;共享门店模式作为一种创新的商业模式&#xff0c;正逐渐成为实体店铺应对电商冲击、提升运营效率和市场竞争力的重要途径。本文将深入解析共享门店模式的内涵、优势、…

通过JS删除当前域名中的全部COOKIE教程

有时候需要通过JS来控制一下网站的登录状态&#xff0c;就例如:网站登出功能&#xff0c;我们可以直接通过JS将所有COOKIE删除&#xff0c;COOKIE删除之后&#xff0c;网站自然也就退出了。 那么今天我就给大家分享一段JS的函数&#xff0c;通过调用这段函数就可以实现删除COO…

QT开发之版本选择

在选择Qt开发版本时&#xff0c;以下是一些建议&#xff1a; 1. **稳定性和广泛使用**&#xff1a;Qt5系列是目前使用最广泛的版本&#xff0c;其中一些长期支持&#xff08;LTS&#xff09;版本因其稳定性和长期维护而受到推荐。 2. **Qt5 LTS版本推荐**&#xff1a;以下是一…

docker desktop运行rabittmq容器,控制台无法访问

docker desktop运行rabittmq容器&#xff0c;控制台无法访问 启动过程&#xff1a;…此处缺略&#xff0c;网上一大堆 原因 原因是在Docker上运行的RabbitMQ&#xff0c;默认情况下是没有启用管理插件和管理页面的 解决办法 使用命令 docker exec -it 容器id /bin/bash 进…

C++中的栈(Stack)和堆(Heap)

在C中&#xff0c;堆&#xff08;heap&#xff09;和栈&#xff08;stack&#xff09;是两种用于存储数据的内存区域。理解它们的原理和区别&#xff0c;对于优化代码性能和确保代码的安全性至关重要。以下是对C中堆栈的详细解析&#xff0c;包括它们的分配方式、优缺点、应用场…

爬虫开发工具与环境搭建——环境配置

第二章&#xff1a;爬虫开发工具与环境搭建 第二节&#xff1a;环境配置 在进行爬虫开发之前&#xff0c;首先需要配置好开发环境。一个良好的开发环境不仅能提高开发效率&#xff0c;还能避免因环境不一致带来的问题。以下是环境配置的详细步骤&#xff0c;涵盖了Python开发…

wpf的C1FlexGrid可见表格合并计算操作

计算动态加载行后的部分字段的计算求和操作 表格上添加事件触发ItemsSourceChanged属性&#xff0c;触发事件 <c1:C1FlexGrid Name"CfgSaleOrderReviewItem" Style"{StaticResource Green}" ItemsSource"{Binding SaleOrderList,ModeTwoWay}"…