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);
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL】sql语句之库操作

序言 在上篇文章学习当中,我们认识了数据库的相关概念,以及MySQL的框架和基本使用等内容,总之对数据库有了一个大致的认识,那么本篇文章将开始关于sql语句的学习,本文主要是关于库的属性和操作的内容,简单可…

2024网络与信息安全管理员职工职业技能竞赛re0220164094

main部分,就是要逆这部分shellcode,程序把data段里面的东西复制到bss段去执行,期间包含解码操作。 v19 0;puts("Please input your flag: ");__isoc99_scanf("%s", s);if ( strlen(s) ! 38 ){puts("Wrong length!&…

yolov5模型结构与构建原理

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

数字信号处理实验四:IIR数字滤波器设计及软件实现

一、实验目的 1. 掌握MATLAB中进行IIR模拟滤波器的设计的相关函数的应用; 2. 掌握MATLAB的工具箱中提供的常用IIR数字滤波器的设计函数的应用; 3.掌握MATLAB的工具箱中提供的模拟滤波器转数字滤波器的相关的设计函数的应用。 二、实验内容 本实验为…

s32k314【入门新手篇】-开发环境安装【ds32开发平台】

软件包下载 登录nxp官网下载:https://www.nxp.com/ 然后输入关键字:S32 查看 下载安装包 以上三步请先注册好并登录你的个人账号 下载完之后如下: 软件安装 eb安装并激活【试用版】 激活 2 安装ds 弹出什么就安装什么就好了。 …

算法设计与分析部分题目解释

目录 第1讲算法引论 作业1-1 1. (单选题, 5分)算法研究领域包括的三个主要方面为( A ) 2. (单选题, 5分)下面说法关于算法与问题的说法错误的是(B)。 3. (单选题, 5分)下面关于程序和算法的说法不正确的是(B)。 4. (单选题,…

[C#]使用OpenCvSharp图像滤波中值滤波均值滤波高通滤波双边滤波锐化滤波自定义滤波

在使用OpenCvSharp进行图像滤波处理时,各种滤波方法都有其特定的用途和效果。以下是对中值滤波、均值滤波、高通滤波、双边滤波、锐化滤波和自定义滤波的详细解释和归纳: 中值滤波(MedianBlur) 原理与作用:中值滤波是…

redis(17):什么是布隆过滤器?如何实现布隆过滤器?

1 布隆过滤器介绍 布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否在一个集合中。它基于位数组和多个哈希函数的原理,可以高效地进行元素的查询,而且占用的空间相对较小,如下图所示: 根据 key 值计算出它的存储位置,然后将此位置标…

springCloud中将redis共用到common模块

一、 springCloud作为公共模块搭建框架 springCloud 微服务模块中将redis作为公共模块进行的搭建结构图&#xff0c;如下&#xff1a; 二、redis 公共模块的搭建框架 如上架构&#xff0c;代码如下pom.xml 关键代码&#xff1a; <dependencies><!-- SpringBoot Boo…

Pycharm 添加内容根

解决问题&#xff1a;包未能被正常引入时

【WRF调试运行第一期】安装WRF模型所需平台

WRF实践实操第一期&#xff1a;安装WRF模型所需平台 1 操作系统2 先决条件软件3 程序流&#xff08;Program Flow&#xff09;4 文件说明软件安装1-Cygwin参考 安装 WRF&#xff08;Weather Research and Forecasting&#xff09;模型需要准备适当的硬件和软件平台。 相关介绍可…

【计算机毕设】基于SpringBoot的中小企业设备管理系统设计与实现 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 在中小企业中&#xff0c;设备管理是确保生产和运营效率的重要环节。传统的设备管理通常依赖于手工记录和人工管理&#xff0c;容易导致数据不准确、…

全球首款AR电脑上线,可投影100英寸屏幕

近日&#xff0c;Sightful公司推出了一款名为Spacetop G1的革命性笔记本电脑&#xff0c;将AR技术与传统笔记本电脑巧妙融合&#xff0c;打造出令人惊叹的全新办公体验。 全球首款AR电脑上线&#xff0c;可投影100英寸屏幕 不同于传统笔记本电脑依赖物理屏幕显示内容&#xff0…

C#WPF数字大屏项目实战11--质量控制

1、区域划分 2、区域布局 3、视图模型 4、控件绑定 5、运行效果 走过路过&#xff0c;不要错过&#xff0c;欢迎点赞&#xff0c;收藏&#xff0c;转载&#xff0c;复制&#xff0c;抄袭&#xff0c;留言&#xff0c;动动你的金手指&#xff0c;财务自由

OJ题目【栈和队列】

题目导入 栈&#xff1a; 题目一&#xff1a;有效的括号题目二&#xff1a;用栈实现队列 队列 题目&#xff1a;实现循环队列 栈 题目一 有效的括号 题目要求 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘…

四川汇聚荣聚荣科技有限公司正规吗?

在当今数字化时代&#xff0c;科技公司如雨后春笋般涌现&#xff0c;而四川汇聚荣聚荣科技有限公司作为其中的一员&#xff0c;其正规性自然成为外界关注的焦点。接下来的内容将围绕这一问题展开深入探讨。 一、公司概况四川汇聚荣聚荣科技有限公司是一家位于成都的高新技术企业…

兆易创新:周期已至 触底反弹?

韩国那边来的数据啊&#xff0c;4月芯片库存同比下降33.7%&#xff0c;创近10年以来&#xff08;最&#xff09;大降幅&#xff0c;芯片出口同比增长53.9%&#xff0c;其中存储芯片出口额同比大幅增长98.7%&#xff0c;开启了涨价模式。沉寂一年多的存储芯片迎来了景气周期。 所…

IO进程线程(五)库的制作、进程

文章目录 一、库&#xff08;一&#xff09;静态库1. 概念2. 制作3. 使用&#xff08;编译&#xff09;&#xff08;1&#xff09;生成可执行文件&#xff08;2&#xff09;运行 &#xff08;二&#xff09;动态库&#xff08;共享库&#xff09;1. 概念2. 制作3. 生成可执行文…

9. MySQL事务、字符集

文章目录 【 1. 事务 Transaction 】1.1 事务的基本原理1.2 MySQL 执行事务的语法和流程1.2.1 开始事务1.2.2 提交事务1.2.3 回滚&#xff08;撤销&#xff09;事务实例1&#xff1a;一致性实例2&#xff1a;原子性 【 2. 字符集 和 校对规则 】2.1 基本原理2.2 查看字符集查看…

Web3.0区块链技术开发方案丨NFT项目开发

在Web3.0时代&#xff0c;非同质化代币&#xff08;NFT&#xff09;的概念正在引领着数字资产领域的变革和创新。NFT作为区块链上的数字资产&#xff0c;具有独一无二的特性&#xff0c;可以代表任何形式的数字或实物资产&#xff0c;并在区块链上进行唯一标识和交易。本文将探…