平衡二叉树的构建(理论,部分函数代码)

        平衡二叉树是二叉排序树的一种特殊情况,平衡二叉树的出现是为了在最坏情况下的时间复杂度仍然是对数级别O(logn),从而保证了高效的搜索、插入和删除操作。

举个例子,如果有一个数组是:1,2,3。如果只简单的排序:

        如图所示,如果想要找到 3 这个元素,那么需要寻找 3 次,比较麻烦,如果换一种排序方式,如第二张图,仍然是二叉排序树,但是这次只需要寻找 2 次即可。

平衡二叉树(AVL)的特点是:

每个节点的左右子树的高度差最多为 1 。

        那么如何实现左右子树的高度差只有 1 呢?这就需要引出文章的内容:四种操作,让普通排序二叉树变成平衡二叉树。

第一种,左旋(Left Rotation)

        这种操作通常在左子树较高的情况下发生,如图,3 节点的左子树高度是2,右子树高度为0。我们要实现左图到右图的转变。

        图中的方块是 2 节点的右子树,可以为空,如果存在,既然方块一开始就在 3 节点的左子树上,所以方块最后也一定在 3 的左子树。

        现在我们可以思考一下具体操作,首先,把 2 的右孩子连接到 3 节点上(无论是否为空),然后把原来的根节点(3节点)连接到 2 节点上,最后更新根节点(变为 2 节点)。

代码如下:

void LL( TreeNode** root) {
	TreeNode* node = NULL;
	node = (*root)->lchild;
	(*root)->lchild = node->rchild;
	node->rchild = (*root);
	(*root)->height = Max(GetTreeHeight((*root)->lchild), GetTreeHeight((*root)->rchild)) + 1;
	node->height = Max(GetTreeHeight(node->lchild), GetTreeHeight(node->rchild)) + 1;
	*root = node;
}

        关于 Max 函数和 GetTreeHeight 函数我下篇文章会详细讲解,首先因为最后要改变根节点指针,所以传二级指针来改变根节点指针的值。旋转代码的关键就四行代码,红色箭头是找到 node 节点,即新的根节点,蓝色圈代表子树的重新构建,绿色箭头是代码的执行顺序。

第二种, 右旋(Right Rotation)

同理,右旋主要发生在右子树比较高的情况下,也就是文章最开始的图例。具体流程如下

        和左旋的原理一模一样,先把 2 节点的左孩子连接到原根节点上,然后把原根节点连接到 2 节点上,然后更新根节点,使 2 节点更新为新根节点,代码如下:

void RR( TreeNode** root) {
	TreeNode* node = NULL;
	node = (*root)->rchild;
	(*root)->rchild = node->lchild;
	node->lchild = (*root);
	(*root)->height = Max(GetTreeHeight((*root)->lchild), GetTreeHeight((*root)->rchild)) + 1;
	node->height = Max(GetTreeHeight(node->lchild), GetTreeHeight(node->rchild)) + 1;
	*root = node;
}

下面是过程图,逻辑和左旋相同,先保留 2 的左节点,更新 2 的左节点,最后更新根节点。

第三种,左-右旋(Left-Right Rotation)

        如果二叉树是这种情况,此时 4 节点的左孩子高度为2,右孩子高度为0,此时需要变成右图中的情况。

        具体操作就是,把 2 节点连接到 3 节点的左孩子,4 节点连接到 3 节点的右孩子,最后更新根节点,使 3 节点变为根节点。

void LR(TreeNode** root) {
	TreeNode* node = NULL;
	node = (*root)->lchild->rchild;
	node->lchild = (*root)->lchild;
	node->rchild = *root;
	(*root)->height = Max(GetTreeHeight((*root)->lchild), GetTreeHeight((*root)->rchild)) + 1;
	node->height = Max(GetTreeHeight(node->lchild), GetTreeHeight(node->rchild)) + 1;
	*root = node;
}

下面是左右旋的流程图: 

 第四种,右-左旋(Right-Left Rotation)

        第四种和第三种原理一样,只不过变成,把 4 节点连接到 3 节点的右孩子,2 节点连接到 3 节点的左孩子,最后更新根节点。

最后直接附上代码了:

void RL(TreeNode** root) {
	TreeNode* node = NULL;
	node = (*root)->rchild->lchild;
	node->lchild = *root;
	node->rchild = (*root)->rchild;
	(*root)->height = Max(GetTreeHeight((*root)->lchild), GetTreeHeight((*root)->rchild)) + 1;
	node->height = Max(GetTreeHeight(node->lchild), GetTreeHeight(node->rchild)) + 1;
	*root = node;
}

这就是文章的全部内容了,希望对你有所帮助,如有错误欢迎评论。

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

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

相关文章

GoldenEye-v1(vulnhub)靶机练习实践报告

GoldenEye-v1****靶机练习实践报告 一、安装靶机 靶机是.ova文件,需要用VirtualBox打开,但我习惯于使用VMWare,因此修改靶机文件,使其适用于VMWare打开。 解压ova文件,得到.ovf文件和.vmdk文件。 用记事本打开.ovf文件并修改“…

汽车制造业安全有效的设计图纸文件外发系统是什么样的?

在汽车制造的世界里,那些设计图不仅仅是公司智慧的闪光点,更是它们竞争的秘密武器。但问题来了,当公司需要和供应商、合作伙伴频繁交换数据时,怎样安全又高效地发送这些设计图,就成了一个头疼的问题。这篇文章会深挖一…

基于Vue uni-app的自定义列表表格信息展示组件

摘要:随着软件技术的不断发展,前端开发面临着越来越多的挑战。特别是在业务场景复杂多变的情况下,如何提高开发效率和降低维护成本成为了关键。本文旨在探讨组件化开发在前端应用中的重要性,并以Vue uni-app自定义列表表格为例&am…

使用虚拟卡注册亚马逊店铺亲测墨西哥、北美都可以亲测~~

这几天测试了使用虚拟信用卡注册墨西哥与北美站的店铺,成功下店,总有人说会被扫,其实去年12月费就有使用卡注册店铺,至今还是好的 当然也不是完全都没有可能店铺不会挂,挂的时候提供账单就好了,直接找客服…

go使用letteravatar生成圆形透明头像图标

官网地址:GitHub - disintegration/letteravatar: Letter avatar generation for Go 我对其中函数改了一下,支持多个字符,效果如下: func TestCreateAvatar(t *testing.T) {GenerateAvatar("Bird Fish", 0, "Bird…

【PG16】后 EL 7 时代,PG 16 如何在 CentOS 7 上运行

↑ 关注“少安事务所”公众号,欢迎⭐收藏,不错过精彩内容~ ★ 本文写于 2023-09-29 PostgreSQL 16 Released 9/14, PostgreSQL 16 正式发布。从发布公告^1 和 Release Notes^2 可以看到 PG16 包含了诸多新特性和增强改进。 性能提升,查询计划…

XPosed项目的接入、模版制作、改名全过程

XPosed项目的接入、模版制作、改名全过程 写在前面 之前写过这篇Xposed Hook 过登录密码验证配置开发Xposed项目的文章,这次的接入使用的是当前最新版Android Studio,接入稍微有些差别,也记录下。 本篇文章主要是写关于XP项目接入、制作XP模…

SQL——SELECT相关的题目(力扣难度等级:简单)

目录 197、上升的温度 577、员工奖金 586、订单最多的客户 596、超过5名学生的课 610、判断三角形 620、有趣的电影 181、超过经理收入的员工 1179、重新格式化部门表(行转列) 1280、学生参加各科测试的次数 1965、丢失信息的雇员 1068、产品销售分…

教你网站如何免费实现https

想要实现https访问最简单有效的的方法就是安装SSL证书。只要证书正常安装上以后,浏览器就不会出现网站不安全提示或者访问被拦截的情况。下面我来教大家怎么去获取免费的SSL证书,又如何安装证书实现https访问。 一、选择免费SSL证书提供商 有多家机构提…

CLI举例:负载分担场景下的源NAT配置(主备设备共用同一个地址池)

CLI举例:负载分担场景下的源NAT配置(主备设备共用同一个地址池) 组网需求 如图1所示,企业的两台FW的业务接口都工作在三层,上下行分别连接路由器。FW与上下行路由器之间运行OSPF协议。上行接口连接同一个ISP。 现在希…

word-主控文档、文档拆分及标书编写技巧建议

一、主控文档 视图-大纲视图-显示文档-插入子文档 子文档一旦更新,主文档也会更新。更新主文档,子文档也会更新 需要注意,不可修改子文档名字 二、上交文件 显示文档-折叠子文档-只显示一级-取消链接-关闭大纲视图-保存 三、文档拆分 根…

数据结构算法题day03

数据结构算法题day03 题目 题目 2.设计一个高效算法&#xff0c;将顺序表L的所有元素逆置&#xff0c;要求算法的空间复杂度为O(1)算法思想&#xff1a; 1、常规的解法&#xff1a; Void reverse (sqlist &L){Elemtype temp; //辅助变量for(i 0,i < L.length; i){temp…

Thinkphp5响应式进销存仓库管理系统

随着企业规模的不断扩大和市场竞争的日益激烈&#xff0c;进销存管理在企业的运营中扮演着越来越重要的角色。为了提高企业的运营效率&#xff0c;降低库存成本&#xff0c;提升客户满意度&#xff0c;越来越多的企业开始引入进销存仓库管理系统。 进销存仓库管理系统是一种集…

【机器学习】深入探索机器学习:线性回归算法的原理与应用

❀线性回归算法 &#x1f4d2;1. 引言&#x1f4d2;2. 线性回归的基本原理&#x1f389;回归方程&#x1f389;最小化误差&#x1f389;线性回归的假设条件 &#x1f4d2;3. 线性回归算法的实现&#x1f4d2;4. 线性回归算法的特征工程&#x1f4d2;5. 线性回归模型评估与优化&…

蓝桥杯练习系统(算法训练)ALGO-932 低阶行列式计算

资源限制 内存限制&#xff1a;64.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 给出一个n阶行列式(1<n<9)&#xff0c;求出它的值。 输入格式 第一行给出两个正整数n,p&#xff1b;   接下来n行&…

oracle准确记录数据提交时间

注意&#xff1a;mysql中的默认值同样记录的是dml操作发出时的时间&#xff0c;并且没有找到mysql中准确记录commit时间的方法。 oracle中数据发生变动时&#xff0c;如何准确记录发生变动时的时间。一般会使用ts字段&#xff0c;该字段使用默认值&#xff0c;default to_char…

JeeSite 4.x and 5.x快速开发平台前端技术探索与实践

一、引言 随着企业信息化建设的不断推进&#xff0c;对于快速、高效、安全的企业级应用需求日益增长。JeeSite作为一款企业级快速开发平台&#xff0c;以其强大的后端功能和灵活的前端架构&#xff0c;为开发者提供了强大的支持。本文旨在探讨JeeSite快速开发平台在前端技术方…

c++——模板初始识

1.函数模板 我们经常用到Swap函数交换两个值。由于需要交换的数据的类型不同&#xff0c;我们就需要写不同参数类型的同名函数&#xff0c;也就是函数重载&#xff1a; 然而这三个函数的逻辑是一样的&#xff0c;写这么多有些多此一举&#xff0c;通过函数模版可以写一个通用…

摸鱼大数据——Hive表操作——文件数据的导入和导出

数据导入和导出 1、文件数据导入 1.1 直接上传文件 window页面上传 需求: 已知emp1.txt文件在windows/mac系统,要求使用hdfs保存此文件 并且使用hivesql建表关联数据 use day06; ​ -- 1- 创建Hive表 create table emp1 (id int,name string,salary int,dept string )row for…

CUDA_VISIBLE_DEVICES‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

问题&#xff1a; 命令行出现CUDA_VISIBLE_DEVICES0 python trainer.py这种命令 这是Linux可以的&#xff0c;但是Windows不行。 解决方案&#xff1a; 这条命令的含义是指定某个GPU来运行程序&#xff0c;我们可以在程序开头添加指定GPU的代码&#xff0c;效果是一样的&…