C/C++ 进阶(5)二叉平衡搜索树(AVL树)

个人主页:仍有未知等待探索-CSDN博客

专题分栏:C++

目录

一、概念

二、平衡因子

三、操作

插入

旋转

左单旋

右单旋

左右双旋

右左双旋


一、概念

二叉平衡搜索树又称AVL树,是一种特殊的二叉搜索树。一般的二叉搜索树在遇到数据有序时,查找的效率比较的低。

而二叉平衡搜索树,为了防止有这种极端的情况出现,其保证了任一节点的左右子树的高度差不超过1,通过控制高度,使查找的次数降低。 

二、平衡因子

二叉平衡搜索树,在对节点的结构进行定义的时候多添加了一个平衡因子的变量(bf),用来判断树是否是平衡的

平衡因子 = 右子树的高度 - 左子树的高度

平衡因子的取值为 :0、+1、-1、+2、-2

当平衡因子为+2、-2的时候,代表了这棵树需要进行调整。

三、操作

插入

插入的步骤就是这些。

为什么调节完,平衡因子为1、-1的时候要向上进行调整? 

如果调节完,平衡因子为1、-1,则在没有调整的时候,平衡因子为0。新增了一个结点之后,高度发生了变化。以当前节点为根节点的子树的高度发生了变化,则以当前节点为其中的一个节点的子树的高度也同样发生了变化,所以需要进行调整。

旋转

对于要通过旋转进行调节平衡因子的情况不细分的话,有4种:左单旋、右单旋、左右双旋、右左双旋。

注意:在进行旋转的时候,对于每个节点的指针变化,要特别的细心。

节点中有三个指针,一个指向左孩子、一个指向右孩子、另外一个指向双亲。

旋转点:进行旋转的一个基准点。就比如左单旋的话,parent就是旋转点。

左单旋

左单旋变换:subrl 变成 parent 的右子树,parent 成为 subr 的左子树。

直接看图变换是不难,但是写代码就会有很多的坑(指针的变换)。

// 左单旋
// 参数是图中的parent,也称为旋转点
void RotateL(node* parent)
{node* subr = parent->right;node* subrl = subr->left;// subrl 成为 parent 的右子树 parent->right = subrl;if (subrl)subrl->parent = parent;subr->left = parent;node* pparent = parent->parent;parent->parent = subr;if (_root != parent){if (pparent->left == parent){pparent->left = subr;}else {pparent->right = subr;}subr->parent = pparent;}else{_root = subr;subr->parent = nullptr;}parent->bf = subr->bf = 0;
}

右单旋

如图是右单旋的情况。

右单旋的变换:sublr 变成 parent 的左子树,将parent 变成 subl 的右子树。

直接看图变换是不难,但是写代码就会有很多的坑(指针的变换)。

// 右单旋
// parent 为旋转点
void RotateR(node* parent)
{node* subl = parent->left;node* sublr = subl->right;// sublr成为parent的左子树parent->left = sublr;// 如果sublr是空的话,不需要更新它的双亲结点,因为空指针不能进行解引用if (sublr)sublr->parent = parent;// parent成为subl的右子树subl->right = parent;// 记录一下这个子树的根节点的双亲结点node* pparent = parent->parent;// 更新parent的双亲节点parent->parent = subl;// 判断该子树的根节点是不是整个子树的根节点// 不是的话,也需要更新该子树的根节点的双亲结点if (_root != parent){if (pparent->left == parent){pparent->left = subl;}else {pparent->right = subl;}subl->parent = pparent;}else{_root = subl;subl->parent = nullptr;}// 更新平衡因子parent->bf = subl->bf = 0;
}

左右双旋

左右双旋的变换:先以 subl 为旋转点进行左单旋,然后再以 parent 为旋转点进行右单旋。

注意:1、指针的变换 2、注意新的节点插入在 b 子树的左子树和右子树的时候,平衡因子的变化。

 

// 左右双旋
// 传参传的节点还是parent
void RotateLR(node* parent)
{node* psubl = parent->left;node* psublr = psubl->right;// 记录之前的 sublr 节点的平衡因子int bf = psublr->bf;// 先以 subl 为旋转点进行左单旋RotateL(parent->left);// 然后再以 parent 为旋转点进行右单旋RotateR(parent);// 在完成旋转调整平衡后,在对该子树的平衡因子进行变换// 至于为什么平衡因子等于这些值,可以去看看我画的图然后进行对比// 还是比较清楚的if (-1 == bf){psubl->bf = psublr->bf = 0;parent->bf = 1;}else if (1 == bf){parent->bf = psublr->bf = 0;psubl->bf = -1;	}else if (0 == bf) // 如果在旋转之前的平衡因子就是为0,则调整完之后的平衡因子都是0{parent->bf = psubl->bf = psublr->bf = 0;}else // 这种情况一般是没有的,如果有,则是你写的AVL树是有错误的{assert(false);}
}

 

右左双旋

右左双旋的变换:先以 subr 为旋转点进行右单旋,然后再以 parent 为旋转点进行左单旋。

注意:1、指针的变换 2、注意新的节点插入在 c 子树的左子树和右子树的时候,平衡因子的变化。

 

// 右左双旋
void RotateRL(node* parent)
{node* psubr = parent->right;node* psubrl = parent->left;int bf = psubrl->bf;// 先以subr为旋转点进行右单旋RotateR(parent->right);// 再以parent为旋转点进行左单旋RotateL(parent);// 更新平衡因子if (1 == bf){psubr->bf = psubrl->bf = 0;parent->bf = -1;}else if (-1 == bf){parent->bf = psubrl->bf = 0;psubr->bf = 1;}else if (0 == bf){parent->bf = psubr->bf = psubrl->bf = 0;}else {assert(false);}
}

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

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

相关文章

路由策略简介

一、路由策略 1、定义: 路由策略(RoutingPolicy)作用于路由,主要实现了路由过滤和路由属性设置等功能,它通过改变路由属性(包括可达性)来改变网络流量所经过的路经。 2、目的 设备在发布、接收和引入路由信息时,根据实际组网需要实施一些策…

微服务开发与实战Day01 - MyBatisPlus

一、微服务 概念:微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合除复杂的大型应用。 课程安排: https://www.bilibili.com/video/BV1S142197x7/?spm_id_from333.1007.top_right_bar_window_history.…

Vue3-Vite-ts 前端生成拓扑图vis,复制即用

完整代码&#xff0c;复制即可用&#xff0c;样式自调 试过 jointjs dagre-d3 vis&#xff0c;好用一点&#xff0c;可添加同层的双向箭头 方法1&#xff1a;Vis.js npm install vis-network <template><div id"mynetwork" class"myChart" :st…

通过DirectML和ONNXRuntime运行Phi-3模型

更多精彩内容&#xff0c;欢迎关注我的公众号“ONE生产力”&#xff01; 上篇我们讲到通过Intel Core Ultra系列处理器内置的NPU加速运行Phi-3模型&#xff0c;有朋友评论说他没有Intel处理器是否有什么办法加速Phi-3模型。通常&#xff0c;使用GPU特别是NVIDA的GPU加速AI模型…

混剪素材库有哪些?分享7个高质量混剪视频素材网站

作为自媒体创作者&#xff0c;我们经常需要高质量的混剪视频素材来吸引观众。今天&#xff0c;我将为大家介绍几个优质的视频素材网站&#xff0c;确保您的短视频制作既高效又充满创意。 蛙学府素材网 首推蛙学府素材网&#xff0c;这个平台真是创作者的福音。无论是短视频素材…

重磅消息! Stable Diffusion 3将于6月12日开源 2B 版本的模型,文中附候补注册链接。

在OpenAI发布Sora后&#xff0c;Stability AI也发布了其最新的模型Stabled Diffusion3, 之前的文章中已经和大家介绍过&#xff0c;感兴趣的小伙伴可以点击以下链接阅读。Sora是音视频方向&#xff0c;Stabled Diffusion3是图像生成方向&#xff0c;那么两者没有必然的联系&…

electron-Vue: Module parse failed: Unexpected character ‘ ‘

​ electron-Vue项目中&#xff0c;我自己写了一个node的C扩展&#xff08;xx.node&#xff09;&#xff0c;然后在.vue文件里import它&#xff0c;然后运行npm run electron:serve&#xff0c;报错如下: ​​ electron-Vue打包默认使用webpack&#xff0c;默认情况下webpack没…

盘点哪些企业容易被ddos攻击

DDoS&#xff08;分布式拒绝服务&#xff09;攻击已成为网络安全威胁中的重要一环。本文将探讨哪些类型的企业容易成为DDoS攻击的目标&#xff0c;并提出相应的防范策略&#xff0c;帮助企业更好地保护自身网络安全。 一、电子商务平台 电子商务平台作为线上交易和支付的重要场…

一文了解JVM(中)

HotSpot 虚拟机对象探秘 对象的创建 Header解释使用 new 关键字调用了构造函数使用 Class 的 newInstance 方法调用了构造函数使用 Constructor 类的newInstance 方法调用了构造函数使用 clone 方法没有调用构造函数使用反序列化没有调用构造函数说到对象的创建,首先让我们看…

6个迹象表明你的电脑电缆管理很糟糕,看下你有没有中招

​清理电脑内部的电缆可能看起来像是徒劳的忙碌。毕竟,如果一切都正常,为什么还要麻烦呢?好吧,我有六个很好的理由可以说服你打开你的机箱,修复你电脑里的混乱。 你很难打开侧板 如果你的电缆离侧板的边缘太近,你将无法毫不费力地将它们滑开。虽然这不是你每天都要做的…

数据结构——图论详细笔记

一 图论基本概念 Directed Acyclic Graph &#xff08;DAG&#xff09; 二 图的存储 ①邻接矩阵(适用于稠密图) ②邻接表(适用于稀疏图) 三、图的遍历 ①深度优先搜索 //(基于邻接表实现&#xff0c;以有向图为例) //DFS:Depth First Search 深度优先搜索 //1、访问起始顶点 …

为什么要开发盲盒小程序?商家企业的盈利方向?

近几年&#xff0c;盲盒已经成为了一种娱乐消费的流行趋势&#xff0c;受到了年轻人的喜欢&#xff0c;推动了盲盒经济的快速发展。在互联网的支持下&#xff0c;盲盒行业也获得了数字化发展&#xff0c;盲盒小程序为市场创新发展提供了重要动力。在当下小程序快速发展的时代&a…

【C++修行之道】类和对象(四)运算符重载

目录 一、 运算符重载 函数重载和运算符重载有什么关系&#xff1f; 二、.*运算符的作用 三、运算符重载的正常使用 四、重载成成员函数 五、赋值运算符重载 1.赋值运算符重载格式 传值返回和引用返回 有没有办法不生成拷贝&#xff1f; 2. 赋值运算符只能重载成类的…

MongoDB CRUD操作:可重试写入

MongoDB CRUD操作&#xff1a;可重试写入 文章目录 MongoDB CRUD操作&#xff1a;可重试写入使用的先决条件部署的限制支持的存储引擎3.6 MongoDB 驱动程序MongoDB 版本写确认 可重试写入和多文档事务启用可重试写入MongoDB驱动mongosh 可重试的写操作行为持续的网络错误故障切…

Linux如何远程连接服务器?

远程连接服务器是当代计算机技术中一个非常重要的功能&#xff0c;在各种领域都有广泛的应用。本文将重点介绍如何使用Linux系统进行远程连接服务器操作。 SSH协议 远程连接服务器最常用的方式是使用SSH&#xff08;Secure Shell&#xff09;协议。SSH是一种网络协议&#xff…

Java常规题技术分享

一、数组排序和添加成员 设计类Student和类StudentClass。 (1) 类Student有字符串属性name、double属性grade和int属性age 有带参数的构造方法&#xff0c;可设置三个属性的值 有各个属性的置取方法 (2)类StudentClass有Student数组属性stus存放班级成员&#xff0c;有int…

「不只是框架:Django REST framework的超能力大揭秘」

想要让你的API服务像五星级餐厅一样令人难忘吗&#xff1f;今天阿佑将为你揭晓&#xff01;从基础的RESTful原则到Django REST framework的高级特性&#xff0c;我们一步步带你走进API开发的后厨&#xff0c;展示如何准备食材&#xff08;数据模型&#xff09;、调制酱料&#…

揭秘GPU技术新趋势:从虚拟化到池化

从GPU虚拟化到池化 大模型兴起加剧GPU算力需求&#xff0c;企业面临GPU资源有限且利用率不高的挑战。为打破这一瓶颈&#xff0c;实现GPU算力资源均衡与国产化替代&#xff0c;GPU算力池化成为关键。本文深入探讨GPU设备虚拟化途径、共享方案及云原生实现&#xff0c;旨在优化资…

yolov5模型结构与构建原理

一.yolov5模型结构与构建原理 修改模型结构&#xff0c;全部在models文件夹下面 models/common.py &#xff08;加入新增网络细节&#xff09; models/yolo.py &#xff08;设定网络结构传参细节&#xff09; models/##.yaml &#xff08;修改模型结构配置文…

kill 不管用时,类型为C

当使用nvidia-smi时看到类型为C的进程时&#xff0c;使用 kill -9 PID&#xff0c;却不管用&#xff0c;这时需要先使用如下命令&#xff0c;找出运行的脚本对应的所有PID: ps -aux | grep train.py 接着就会把train.py对应运行的进程全部展示出来&#xff1a; 接着就是使用 …