《堆》的模拟实现

news2025/2/27 5:05:25

目录

前言:

模拟实现《堆》:

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

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

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

相关文章

锐捷RG-UAC应用网关 前台RCE漏洞复现

0x01 产品简介 锐捷RG-UAC系列应用管理网关是锐捷自主研发的应用管理产品。 0x02 漏洞概述 锐捷RG-UAC应用管理网关 nmc_sync.php 接口处存在命令执行漏洞&#xff0c;未经身份认证的攻击者可执行任意命令控制服务器权限。 0x03 复现环境 FOFA&#xff1a;app"Ruijie-R…

软著项目推荐 深度学习手势识别算法实现 - opencv python

文章目录 1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估 6 识别效果7 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习手势识别算法实现 - opencv python 该项目较为新颖…

宝塔面板:轻松玩转linux系统,实现服务器状态监控和运维部署!

. linux安装 安装命令概述基本设置软件安装设置安全设置文件管理日志模块终端模块计划任务卸载命令windows服务器安装 下载卸载遗留user.ini文件删除报错 宝塔面板是一款服务器管理软件&#xff0c;旨在提升运维效率。它支持一键安装LAMP/LNMP/集群/监控/网站/FTP/数据库/JAVA等…

【代码】计及碳捕集电厂低碳特性及需求响应的综合能源系统多时间尺度调度模型matlab/yalmip代码

程序名称&#xff1a;计及碳捕集电厂低碳特性及需求响应的综合能源系统多时间尺度调度模型 实现平台&#xff1a;matlab-yalmip-cplex/gurobi 代码简介&#xff1a;代码主要做的是一个虚拟电厂/微网多时间尺度电热综合能源系统低碳经济调度模型&#xff0c;源侧在碳捕集电厂中…

2024年美国大学生数学建模竞赛(MCM/ICM)论文写作方法指导

一、前言 谈笑有鸿儒&#xff0c;往来无白丁。鸟宿池边树&#xff0c;僧敲月下门。士为知己者死&#xff0c;女为悦己者容。吴楚东南坼&#xff0c;乾坤日夜浮。剪不断&#xff0c;理还乱&#xff0c;是离愁&#xff0c;别是一番滋味在心头。 重要提示&#xff1a;优秀论文的解…

Linux 匿名页反向映射

1. 何为反向映射 正向映射&#xff1a; 用户进程在申请内存时&#xff0c;内核并不会立刻给其分配物理内存&#xff0c;而是先为其分配一段虚拟地址空间&#xff0c;当进程访问该虚拟地址空间时&#xff0c;触发page fault异常&#xff0c;异常处理流程中会为其分配物理页面&am…

哪一款台灯适合学生考研用?热门学生护眼台灯推荐

近些年近视人数持续升高&#xff0c;我们越来越注意个人的健康问题&#xff0c;而对于视力健康&#xff0c;尤其是儿童青少年们&#xff0c;在3-14岁这个年龄段近视机率更高&#xff0c;儿童青少年近视率高达52.7%&#xff0c;随着市面上护眼台灯的种类越来越多&#xff0c;各种…

OpenTelemetry系列 - 第1篇 相关概念

目录 一、背景二、概念2.1 Traces & Span2.2 Metrics2.3 Logs2.4 Baggage2.5 OTel2.6 OTLP2.7 Resources2.8 Instrumentation Scope2.9 Sampling 三、核心组件 一、背景 OpenTelemetry是一个可观察性框架和工具包&#xff0c;旨在创建和管理遥测数据&#xff0c;如跟踪、指…

运维 | 关于IP网络相关的概念和原理

关注&#xff1a;CodingTechWork IP地址 IP介绍 概述 IP是TCP/IP协议族的核心&#xff0c;IP地址是电脑在网络中的唯一标识&#xff0c;全球唯一&#xff08;G公网IP&#xff09;。IP地址&#xff08;Internet Protocol Address&#xff09;是互联网协议地址&#xff0c;也…

LabVIEW在不同操作系统上使VI、可执行文件或安装程序

LabVIEW在不同操作系统上使VI、可执行文件或安装程序 LabVIEW可以在多个操作系统上运行&#xff0c;主要支持以下几种操作系统&#xff1a; Windows&#xff1a; LabVIEW在各个版本的Windows操作系统上都能运行&#xff0c;包括Windows 7、Windows 8和Windows10。LabVIEW为Wi…

【数据中台】开源项目(5)-Amoro

介绍 Amoro is a Lakehouse management system built on open data lake formats. Working with compute engines including Flink, Spark, and Trino, Amoro brings pluggable and self-managed features for Lakehouse to provide out-of-the-box data warehouse experience,…

海外之路,英语相助:我的雅思考试之旅(成功以此申请到了港科大硕士)

文章目录 背景注册过程 雅思考试之旅全程记录2023年2月14日 - 报名补充2023年2月15日 - 模拟考试2023年2月16日 - 在线考试失利2023年2月20日 - 线下考试再战成功2023年2月23日 - 成绩出来了 考试经验寄送成绩问题请求额外的IELTS成绩寄送 结语 背景 在新加坡Shopee工作了两年…

【面试经典 150 | 二分查找】搜索插入位置

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;二分查找闭区间左闭右开区间开区间总结 知识总结写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c…

【Python 训练营】N_14 文件查找和替换

题目 新建一个test3.txt文件&#xff0c;内容如下图&#xff0c;然后从中查找字符串’five’&#xff0c;并统计出现的次数&#xff1b;替换其中的’five’字符串为’python’。 分析 类似Excel中的查找和替换&#xff0c;查找相应内容需用到正则&#xff0c;还考察文件打开、…

持续集成交付CICD:CentOS 7 安装 Sonarqube9.6

目录 一、实验 1.CentOS 7 安装 Sonarqube9.6 二、问题 1.安装postgresql13服务端报错 2.postgresql13创建用户报错 一、实验 1.CentOS 7 安装 Sonarqube9.6 &#xff08;1&#xff09;下载软件及依赖包 ①Sonarqube9.6下载地址 https://binaries.sonarsource.com/Dis…

欧洲各国及发达国家经济支柱和第一出口商品是什么

工业在欧洲各国经济支柱中的表现 一般发达国家&#xff0c;像西欧的国家第三产业即服务业占GDP70%甚至更高&#xff0c;从业人数比重也最大&#xff0c;只是越发达的国家服务业的知识性和科技含量会更高&#xff0c;如商业咨询、律师、医疗卫生、科技服务、商业服务。服务业的…

布隆过滤器,Redis之 bitmap,场景题【如果微博某个大V发了一条消息,怎么统计有多少人看过了】

学习文档 文章目录 一、什么是 Bitmap1-1、Bitmap 相关命令 二、Bitmap 和 Set 对比2-1、数据准备2-2、内存对比2-3、性能对比 三、布隆过滤器3-1、理论3-2、代码实现 四、Java中的 Hash 函数 最近面试时&#xff0c;遇到了一个场景题&#xff0c;面试官问如何统计一条微博大V的…

计算机网络扫盲(1)——因特网

一、概述 因特网是一个世界范围的计算机网络&#xff0c;即它是一个互联了遍及全世界数十亿计算设备的网络。大家对此应该并不陌生&#xff0c;我们身边有着不计其数的计算机设备被接入了因特网&#xff0c;如今计算机网络这个术语似乎已经有点过时了&#xff0c;用因特网的术语…

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

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

MyBatis增删改查和配置文件

MyBatis增删改查 MyBatis新增 新增用户 持久层接口添加方法 void add(User user);映射文件添加标签 <insert id"add" parameterType"com.mybatis.pojo.User">insert into user(username,sex,address) values(# {username},# {sex},# {address}) <…