AVL树的平衡算法的简化问题

news2025/3/16 22:06:40

AVL树是一种紧凑的二叉查找树。它的每个结点,都有左右子树高度相等,或者只相差1这样的特性。文章https://blog.csdn.net/aaasssdddd96/article/details/106291144给出了一个例子。

为了便于讨论,这里对AVL树的结点平衡情况定义2个名称,如果两边左右子树高度相等,称之为真平衡,如果两边高度相差1,称之为准平衡。真平衡和准平衡的这个意义只限于在本文的讨论。准平衡有2种情况,所以实际是3种情况。

当AVL树中插入一个新结点时,它的父结点如果是真平衡,那么状态转化为准平衡,树的高度增加了1,因为高度增加,这个父结点需要接着向更高一层的父结点报告这个变化。

如果父结点是准平衡,那么也有2种情况。如果增加的高度是在较矮的一侧,那么父结点状态转为真平衡,操作完成;如果增加的高度是在较高的一侧,那么结点的平衡因子超限,这种情况在上面第一种情况的最后一个变化发生,需要进行平衡调整。调整之后,恢复为真平衡,局部高度不增,操作完成。

这些问题不难。真正让初学者感到烦恼的是平衡调整。调整分4种情况,分别称为“LL-旋转”,“LR-旋转”,“RL-旋转”,“RR-旋转”。后2种和前两种镜像对应。编写这部分代码的时候,最好写完前2种,休息20分钟,再去复制前面的代码,逐条改成它的镜像。休息片刻是为了避免头晕,转来转去转的头一晕,修改镜像时随便漏掉一条,就会带来极为费时难调的bug。这样编程并没有什么不对,这是需要掌握的基本功,而且实际开发过程也会常常碰到需要蛮力硬搞来攻克的难题。

但在这里是否有比硬搞好一点的办法?

如果在构造AVL树时,预分配3个储备结点会怎么样。左、中、右,预先结成一个三角形。但不在AVL树中,而是备用:

struct avl_help {
	struct node *root;
	struct triangle {
		struct node *left;
		struct node *mid;
		struct node *right;
	} help;
};

struct avl_help avl;

初始化为:


avl.root=NULL;
avl.help.left = (struct node*)malloc(sizeof(struct node));
avl.help.mid = (struct node*)malloc(sizeof(struct node));
avl.help.right = (struct node*)malloc(sizeof(struct node));

avl.help.mid->left=avl.help.left;
avl.help.mid->right=avl.help.right;
avl.help.left->parent=avl.help.mid;
avl.help.right->parent=avl.help.mid;

现在大家都想到了:在AVL树需要发生平衡调整的时候,把已经调好的3个储备结点拿出来,整体替换掉树中需要调整的3个结点,再把替换下来的原来的3个结点做成初始化中的左、中、右三角结构,存回到help中储备,留给下次用。这样调整就完成了。而替换下来的3个结点只要把头结点连到中间结点的左指针,或右指针,具体看那个指针空闲,就重新构成了三角结构。

以“LR型-旋转”为例,调整操作大致是这样子。假设ap0,ap1,ap2三个指针已经分别指向LR型的待调整的上中下3个结点:

help= &avl.help;
help->left->left=ap1->left;
help->left->right=ap2->left;
help->left->tag=(ap2->tag==1?0:-1);

help->right->left=ap2->right;
help->right->right=ap0->right;
help->right->tag=(ap2->tag==-1?1:0);

help->mid->tag=0;
if(help->left->left)
help->left->left->parent=help->left;
if(help->left->right)
help->left->right->parent=help->left;
if(help->right->left)
help->right->left->parent=help->right;
if(help->right->right)
help->right->right->parent=help->right;
help->mid->parent=ap0->parent;

if(help->mid->parent==NULL)
avl->root= help->mid;
else if(help->mid->parent->left==ap0)
help->mid->parent->left=help->mid;
else help->mid->parent->right=help->mid;

而存回替换下来的ap0,ap1,ap2三个结点的代码就是:

ap1->left=ap0;
ap0->parent=ap1;
help->left= ap0;
help->mid=ap1;
help->right=ap2;

其它几种情况可以类推,大同小异,这里就不重复了。

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

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

相关文章

mac安装navicat及使用

0.删除旧的 sudo rm -Rf /Applications/Navicat\ Premium.app sudo rm -Rf /private/var/db/BootCaches/CB6F12B3-2C14-461E-B5A7-A8621B7FF130/app.com.prect.NavicatPremium.playlist sudo rm -Rf ~/Library/Caches/com.apple.helpd/SDMHelpData/Other/English/HelpSDMIndexF…

【HTML】二、列表、表格

文章目录 1、列表1.1 无序列表1.2 有序列表1.3 定义列表 2、表格2.1 定义2.2 表格结构标签2.3 合并单元格 1、列表 列表分为: 无序列表有序列表定义列表:一个标题下有多个小分类 1.1 无序列表 ul嵌套li,ul是无序列表,li是列表…

​​​​​​​大语言模型安全风险分析及相关解决方案

大语言模型的安全风险可以从多个维度进行分类。 从输入输出的角度来看,存在提示注入、不安全输出处理、恶意内容生成和幻觉错误等风险; 从数据层面来看,训练数据中毒、敏感信息泄露和模型反演攻击是主要威胁; 模型自身则面临拒绝服务和盗窃的风险; 供应链和插件的不安全引…

windows平台的ffmpeg编译使用

windows平台的ffmpeg编译使用 一、现状 本人使用libgdx开发galGame,发现扩展包gdx-video不支持mp4,不能忍,正好看到官网有支持自定义编译的文档,所以操作一下,自定义编译。本文重点在于操作windows平台,linux平台太简单了。 整个过程包括如下几个步骤。 二、代码下载…

FFMPEG录制远程监控摄像头MP4

手绘效果图 上图是录制功能的HTML前端页面,录制功能和解码视频放在一起。录制功能关键是录制(开始录制按钮)、停止录像按钮。当点击“录制”的时候则会开始录制MP4文件, 当点击停止的时候就会停止录制MP4。经过录制后,则会生成MP4,并放到我的RV1126的/tm…

centos操作系统上传和下载百度网盘内容

探序基因 整理 进入百度网盘官网百度网盘 客户端下载 下载linux的rpm格式的安装包 在linux命令行中输入:rpm -ivh baidunetdisk_4.17.7_x86_64.rpm 出现报错: 错误:依赖检测失败: libXScrnSaver 被 baidunetdisk-4.17.7-1.x8…

Rubick:基于 Electron 的开源插件化桌面效率工具箱

Rubick 是一款基于 Electron 构建的开源桌面工具箱,专为追求高效办公和个性化体验的用户设计。它通过自由集成丰富的插件,让用户能够根据自己的需求打造极致的桌面端效率工具。 软件命名由来Rubick 的名字来源于《DOTA2》中的英雄 Rubick(拉…

ruoyi-vue部署

ruoyi源码类型 Ruoyi源码 编译打包后,直接部署tomcat服务器 Ruoyi-vue 前后端分离版 前端部署到nginx 后端部署到tomcat RuoYi-Cloud 微服务版 RuoYi-app 移动端版 RuoYi-vue 前后端分离版 环境 JDK>=1.8 MySQL >= 5.7 Maven >= 3.0 Node >= 12 Redis…

LLM论文笔记 23: Meta Reasoning for Large Language Models

Arxiv日期:2024.6.17机构:THU / MSRA 关键词 meta-reasoning推理方法prompt engineering 核心结论 1. 提出Meta Reasoning prompting,MRP是一种系统提示方法,能够帮助LLM动态选择最合适的推理方法,从而提升其灵活性和…

【最后203篇系列】015 几种消息队列的思考

背景 队列还是非常重要的中间件,可以帮助我们:提高处理效率、完成更复杂的处理流程 最初,我觉得只要掌握一种消息队列就够了,现在想想挺好笑的。 过去的探索 因为我用python,而rabbitmq比较贴合快速和复杂的数据处…

学习springboot 的自动配置原理

前言 为什么要学习springboot 的自动配置原理? 1学习 自定义成starter 的前提 实际开发中,我们如果定义公共的组件给团队使用,为了让他们使用方便就自定义成starter。而想要学习starter ,就要先了解springboot 的自动配置原理 2 面试需要 了…

排错 -- FISCO BCOS区块链网络 -- 3. 编译智能合约

文章为FISCO BCOS2.0搭建区块链平台中发现的问题与总结,出错原因不唯一 ,解决办法不唯一 目前社区缺少完整,稳定的搭建平台和教程 ,欢迎各位及时补充,如有错误请及时评论纠正! 感谢各位搜索到这里&#…

ffmpeg 添加毫秒时间戳

网上有好多添加时间水印的,默认是到秒,而我需要到毫秒,查了一下,没有找到更好的方案,下面是自己实现的方案,可以显示到毫秒。如果有更好的方案,欢迎讨论 ffmpeg -i video.mp4 -vf "drawte…

centos7上安装Docker

文章目录 **1. 使用华为云镜像源替换Docker仓库****2. 安装Docker CE****3.更换docker镜像源-使用华为云的docker镜像源****4.补充:docker的使用****5.补充:删除docker的步骤** 1. 使用华为云镜像源替换Docker仓库 步骤: 删除无效的Docker仓…

【Linux内核系列】:文件系统收尾以及软硬链接详解

🔥 本文专栏:Linux 🌸作者主页:努力努力再努力wz 💪 今日博客励志语录: 世界上只有一种个人英雄主义,那么就是面对生活的种种失败却依然热爱着生活 内容回顾 那么在之前的学习中,我们…

视频理解之Actionclip(论文宏观解读)

配合解读代码解读 1.研究背景 1. 视频行为识别的重要性 视频行为识别是视频理解领域的核心任务之一,旨在通过分析视频内容来识别和分类其中的人物行为或活动。这一任务在多个领域具有重要的应用价值,例如智能监控、人机交互、自动驾驶、医疗健康等。随…

navicat16 升级到 navicat17 之后原来的连接找不到了 mac用户

版本16的路径 注意把对应的路径改成自己的用户名 /Users/自己的用户名/Library/Application Support/PremiumSoft CyberTech/Navicat CC/Common/Settings 版本17的路径 /Users/自己的用户名/Library/Containers/com.navicat.NavicatPremium/Data/Library/Application Suppor…

Altium Designer——CHIP类元器件PCB封装绘制

文章目录 PCB封装组成元素:焊盘的属性 SS34肖特基二极管SMA(DO-214AC)封装绘制资料:步骤:1.绘制焊盘:用到的快捷键:资料: 2.绘制丝印:用到的快捷键:资料: PCB封装组成元素…

【一起来学kubernetes】12、k8s中的Endpoint详解

一、Endpoint的定义与作用二、Endpoint的创建与管理三、Endpoint的查看与组成四、EndpointSlice五、Endpoint的使用场景六、Endpoint与Service的关系1、定义与功能2、创建与管理3、关系与交互4、使用场景与特点 七、Endpoint的kubectl命令1. 查看Endpoint2. 创建Endpoint3. 编辑…

《AI浪潮中的璀璨新星:Meta Llama、Ollama与DeepSeek的深度剖析》:此文为AI自动生成

《AI浪潮中的璀璨新星:Meta Llama、Ollama与DeepSeek的深度剖析》:此文为AI自动生成 引言:AI 大模型的群雄逐鹿时代 在科技飞速发展的当下,AI 大模型领域已成为全球瞩目的焦点,竞争激烈程度堪称白热化。从 OpenAI 推出…