《堆》的模拟实现

目录

前言:

模拟实现《堆》:

1.自定义数据类型

2.初始化“堆”

3.销毁“堆”

4.进“堆”

关于AdjustUp()

5.删除堆顶元素

关于AdjustDown()

6.判断“堆”是否为空

7.求“堆”中的数据个数 

8.求“堆”顶元素

总结:


前言:

我们在上一篇的blog中对于《树》有了初步的认识,树的包含多种数据结构,其中我们现阶段最适合引入“堆”的概念,我们同时也在上一篇的blog中的最后引入并介绍了“堆”的相关概念,了解到了小堆以及大堆。具体内容可以参考上一篇blog:

初识《树》-CSDN博客

本次blog就以小堆为例,动手模拟开辟出一个“小堆”!

模拟实现《堆》:

1.自定义数据类型

typedef int HPDataType;

typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

是的,本次堆的实现我们利用到了顺序表的存储概念,我们在后面会讲到为什么要使用顺序表。

2.初始化“堆”

void HeapInit(HP* php)
{
	php->a = NULL;
	php->capacity = php->size = 0;
}

3.销毁“堆”

void HeapDestory(HP* php)
{
	assert(php);
	php->size = php->capacity = 0;
	free(php->a);
}

 初始化和销毁这两个函数在我们之前的blog中有讲解,而且内容相差不大所以我们在这里不给予讲解,我也不再进行过多赘述。

4.进“堆”

void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	int newcapacity = (php->capacity == 0) ? 4 : 2 * php->capacity;
	HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType)* newcapacity);
	if (tmp == NULL)
	{
		perror("realloc error");
		exit(-1);
	}

	php->a = tmp;
	php->capacity = newcapacity;
	php->a[php->size] = x;
	AdjustUp(php->a, php->size);//向上调整建堆
	php->size++;
}

这里的开头也是与之前的顺序表一致,不同的地方在于我们创建了一个AdjustUp函数。

接下来我们就来讲解此函数:

关于AdjustUp()

void swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

void AdjustUp(HPDataType* a, int child)
{
	while (child > 0)
	{
		int parent = (child - 1) / 2;
		if (a[parent] > a[child])
		{
			swap(&a[parent], &a[child]);
		}
		child = parent;
	}
}

 我们先假设有一个数组,数组元素2,4,5,1,3

现在想要建小堆并让这些数据进“堆”,

还明显,该树并不是堆,既不满足小堆,更不满足堆!

所以我们需要进行调整,所以就有了向上调整法即AdjustUp()

具体的思路:

1.每插入一个数据,就于父亲节点相比较

2.如果父亲节点>孩子节点 那么数据进行交换,由于这是顺序表所以就是数组下标进行交换,同时注意我们在实现交换函数时,传递的是地址

在此我用图来展示:

此时遍历到1这个小标,因为随着数据的添加,size也会++,所以数据1的下标就为size-1

那么我们就让size-1下标即数据1的位置座位child。

而我们想要找到数据1的父亲节点,不难得出公式

parent = (child - 1)/2

 则可找到数据4作为父亲节点,然后进行交换,即:

虽然交换完了数据1和数据4的节点,但是这还不是一个合格的堆,因此我们还要继续进行操作,这个时候我们的child就可以挪动到parent的位置即:

 

 

我们先要将数据1和数据2进行交换,交换完后才是一个小堆,所以这就是while循环在此的作用,而限制条件显而易见就是child不在首元素时状态。

所以parent = (child - 1) / 2

 

进行交换则有:

 

如此就是一个小堆了

 

5.删除堆顶元素

void HeapPop(HP* php)
{
	assert(php);
	//交换头尾元素
	swap(&php->a[0], &php->a[php->size - 1]);

	php->size--;
	//向下调整
	AdjustDown(php->a, php->size, 0);
}

在我们熟悉进“堆”操作后,我们不妨来实现实现删除堆顶数据,具体的操作思路如下:

1.将首元素数据和最后一个数据交换。

2.再调整堆使其完善成小堆。

第一个步骤好理解,接下来我们就来介绍我们的第二个函数,AdjustDown()

关于AdjustDown()

void AdjustDown(HPDataType* a, int sz, int parent)
{
	int child = 2 * parent + 1;
	while (child < sz)
	{
		if (child + 1 < sz && a[child] > a[child + 1])
		{
			child++;
		}
		
		if (a[child] < a[parent])
		{
			swap(&a[child], &a[parent]);
			parent = child;
		}
		else
		{
			break;
		}
	}
}

就拿刚刚的堆来举例,如图:

 先进行首尾互换,则有:

此时我们先让size-- 

目的是为了不管最后一个元素一,即:

可此时并不是一个合格的小堆,但是我们此时不能使用 向上调整法了,因为如果我们首元素一旦是一个很大的数,拿8举例,执行交换就是8和2进项交换,但是8仍然大于4,所以向上调整法不适用这里,因此我们可以得知向上调整法是适用于建堆!

那我们就要利用一种新的思路:

1.从首元素开始向下调整。

2.判断左孩子和右孩子的数哪个更小

3.取小的开始不断交换

我们在这里用图来说明:

我们在此是传递首元素,即父亲进来,那么我们可以通过公式

child = 2*parent + 1

找出左孩子的节点,然后进行判断:

此时很明显左孩子小于右孩子所以进行判断

此时2<3所以进行交换

 

然后继续往下判断,parent = child;

 

继续通过公式有:

 

最后就有:

 

此时child还会继续找下一个数据,可是后续的数据就不是我们的数组内容了,因此交换的条件应当是child< size才能进行交换。

以上这两个函数就是本文的核心精华内容!

 

6.判断“堆”是否为空

bool HeapEmpty(HP* php)
{
	assert(php);
	if (php->size == php->capacity)
	{
		return true;
	}
	return false;
}

7.求“堆”中的数据个数 

int HeapSize(HP* php)
{
	assert(php);
	return php->size;
}

8.求“堆”顶元素

int HeapTop(HP* php)
{
	assert(php);
	if (!HeapEmpty(php))
	{
		return php->a[0];
	}
	exit(-1);
}

总结:

以上就是《堆》的模拟实现的全部内容,我们在实现AdjustUp函数和AdjustDown函数时不难发现,我们要经常找到上一个父亲节点的数据,所以我们才采取顺序表的结构来帮助我们查找。

下一篇的blog我们利用堆这一结构解决问题,包括《堆排序》,《Top-K》。

记住“坐而言不如起而行”

Action speak louder than words!

本文的代码在我的Gitee仓库:

Data structures amd algorithms: 关于数据结构和算法的代码 - Gitee.com

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

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

相关文章

中国人工智能

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;作为一项前沿技术在各个领域展现出了强大的潜力。本文将探讨中国人工智能的历史、现状&#xff0c;并展望其未来发展。 人工智能的起源与历史 人工智能的概念最早诞生于1956年的美国达特茅斯学院的夏季研讨会…

2022年4月12日 Go生态洞察:何时使用泛型 ️

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

目标检测——Fast R-CNN算法解读

论文&#xff1a;Fast R-CNN 作者&#xff1a;Ross Girshick 链接&#xff1a;https://arxiv.org/abs/1504.08083 代码&#xff1a;https://github.com/rbgirshick/fast-rcnn 目录 1、算法概述2、Fast R-CNN细节2.1The RoI pooling layer2.2 Fine-tuning for detection2.3 Fast…

火星探索:技术挑战与前沿进展

火星探索:技术挑战与前沿进展 一、引言 火星,这颗红色的星球,长久以来一直吸引着人类的目光。随着科技的飞速发展,火星探索已经从纯粹的科幻梦想逐渐转变为现实的研究课题。然而,火星探索仍然面临着诸多技术挑战。本文将深入探讨火星探索的关键技术、现有技术瓶颈以及前沿…

【FPGA图像处理实战】- 图像基础知识

视频图像处理是FPGA主要应用方向之一&#xff0c;很多FPGA从事或准备进入这一领域&#xff0c;我们现在开始发布新的FPGA实战专栏——FPGA图像处理。 FPGA处理视频图像处理的主要优势是流水线和并行处理运算&#xff0c;特别是现在视频分辨率越来越大&#xff0c;从720p到1080…

文字、图片免费生成视频和专属数字人,你不来试试吗?

查看生成的效果&#xff1a;AI产生的视频&#xff08;关注公众号&#xff0c;获取精彩内容&#xff09; 您是否想要制作一些令人惊叹的视频&#xff0c;但又没有视频编辑的技能或经验&#xff1f;您是否想要利用人工智能的力量&#xff0c;让您的图片和声音变成动态的视频&…

二叉树链式结构的实现——C语言

目录 一、提前说明 二、二叉树的遍历 2.1前序遍历 2.2中序遍历 2.3后序遍历 2.4代码 三、二叉树结点个数 3.1整体思路 3.2代码 四、二叉树叶子结点个数 4.1整体思路 4.2代码 五、二叉树的高度(深度) 5.1整体思路 5.2代码 六、二叉树第k层节点个数 6.1整体…

selenium三猛士

selenium包括三个项目&#xff0c;分别是&#xff1a;Selenium WebDriver,Selenium IDE&#xff0c;Selenium Grid。 Selenium WebDriver Selenium WebDriver是客户端API接口&#xff0c;测试人员通过调用这些接口&#xff0c;来访问浏览器驱动&#xff0c;浏览器再访问浏览器…

数学建模 | MATLAB数据建模方法--机器学习方法

近年来&#xff0c;全国赛的题目中&#xff0c;多多少少都有些数据&#xff0c;而且数据量总体来说呈不断增加的趋势&#xff0c; 这是由于在科研界和工业界已积累了比较丰富的数据&#xff0c;伴随大数据概念的兴起及机器学习技术的发展&#xff0c; 这些数据需要转化成更有意…

Linux的基本指令(4)

目录 20.tar指令&#xff08;重要&#xff09;&#xff1a;打包/解包&#xff0c;不打开它&#xff0c;直接看内容 21.bc指令 22.uname –r指令&#xff1a; 23.重要的几个热键[Tab],[ctrl]-c, [ctrl]-d 20.tar指令&#xff08;重要&#xff09;&#xff1a;打包/解包&#…

Kubernetes(K8s)Pod控制器详解-06

Pod控制器详解 Pod控制器介绍 Pod是kubernetes的最小管理单元&#xff0c;在kubernetes中&#xff0c;按照pod的创建方式可以将其分为两类&#xff1a; 自主式pod&#xff1a;kubernetes直接创建出来的Pod&#xff0c;这种pod删除后就没有了&#xff0c;也不会重建 控制器创建…

分享85个节日PPT,总有一款适合您

分享85个节日PPT&#xff0c;总有一款适合您 85个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1FTbSj2Baix-Cj6n42Cz26g?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。…

语义分割 U-net网络学习笔记 (附代码)

论文地址&#xff1a;https://link.springer.com/chapter/10.1007/978-3-319-24574-4_28 代码地址&#xff1a;https://b23.tv/PCJJmqN 1.是什么&#xff1f; Unet是一种用于图像分割的深度学习网络模型&#xff0c;其结构由编码器和解码器组成&#xff0c;可以对图像进行像素…

深度学习 -- 神经网络

1、神经网络的历史 2、 M-P模型 M-P模型是首个通过模仿神经元而形成的模型。在M-P模型中,多个输入节点对应一个输出节点y。每个输入x,乘以相应的连接权重w,然后相加得到输出y。结果之和如果大于阈值h,则输出1,否则输出0。输入和输出均是0或1。 公式2.1&#xff1a; …

【代码】多种调度模式下的光储电站经济性最优 储能容量配置分析matlab/yalmip

程序名称&#xff1a;多种调度模式下的光储电站经济性最优储能容量配置分析 实现平台&#xff1a;matlab-yalmip-cplex/gurobi 代码简介&#xff1a;代码主要做的是一个光储电站经济最优储能容量配置的问题&#xff0c;对光储电站中储能的容量进行优化&#xff0c;以实现经济…

08-中介者模式-C语言实现

中介者模式&#xff1a; Define an object that encapsulates how a set of objects interact.Mediator promotes loose coupling by keeping objects from referring to each other explicitly,and it lets you vary their interaction independently.&#xff08;用一个中介对…

2243:Knight Moves

文章目录 题目描述思路1. DFS2. BFS3. 动态规划 解题方法1. DFS2. BFS3. 动态规划 题目描述 题目链接 翻译如下&#xff1a; 注&#xff1a;骑士移动是和象棋里的马一样走的是日字型 你的一个朋友正在研究旅行骑士问题 &#xff08;TKP&#xff09;&#xff0c;你要找到最短的…

结合贝叶斯定理浅谈商业银行员工异常行为排查

1.贝叶斯定理的数学表达 贝叶斯方法依据贝叶斯定理。关于贝叶斯定理解释如下&#xff1a;首先我们设定在事件B条件下&#xff0c;发生事件A的条件概率&#xff0c;即 &#xff0c;从数学公式上&#xff0c;此条件概率等于事件A与事件B同时发生的概率除以事件B发生的概率。 上述…

VUE语法-(readonly的用法)将数据设置成只读模式

1、功能概述 在Vue中定义一个变量&#xff0c;这个变量的值不允许被修改&#xff0c;核心是通过readonly设置成只读。 如果不会使用ref和reactive响应式数据参考如下博客&#xff1a; https://blog.csdn.net/tangshiyilang/article/details/134701103 2、具体实现 如下案例…

轻量级万物分割SAM模型——MobileSAM安装实测摘要

目录 0、前言1、准备工作安装python环境说明安装说明 运行测试app安装依赖修改代码 2、实际测试效果自带图片测试其它图片测试1其它图片测试2 总结 0、前言 本文将介绍一种轻量级万物分割SAM模型——MobileSAM的安装和实测情况。SAM是meta公司的一种图像分割大模型&#xff0c…