【数据结构】堆(Heap)详解----定义堆、初始化,删除、插入、销毁、判空、取堆顶

news2024/12/23 13:12:51

文章目录

  • 一、堆的概念及其性质:
    • 堆的概念:
    • 堆的性质:
  • 二、堆的定义及其基础操作的代码实现(C语言版)
    • 1.定义堆
    • 2.堆的初始化
    • 3.堆的销毁
    • 4.堆的插入
    • 5.堆的删除
    • 6.取堆顶的数据
    • 7.堆的数据个数
    • 8.堆的判空
  • 总结:


提示:以下是本篇文章正文内容

一、堆的概念及其性质:

堆的概念:

:是一种特殊的完全二叉树,使用数组进行存储,其所有的父结点大于等于或者小于等于它们的子结点,所以堆分为大根堆和小根堆。
大根堆(最大堆)::所有的父结点大于等于它们的子结点,堆顶是最大值。
小根堆(最小堆)::所有的父结点小于等于它们的子结点,堆顶是最小值。
举例
在这里插入图片描述
在这里插入图片描述

堆的性质:

对于具有n个结点的完全二叉树,若按照从上至下,丛左至右的数组顺序对所有结点从0开始编号,则对于序号为i的节点:
1.若i=0,i为根节点编号,无双亲结点。
2.若i>0,i位置结点的双亲序号:(i-1)/2;
3.若2i+1<n,左孩子序号:2i+1。
4.若21+2<n,右孩子序号:2i+2。

二、堆的定义及其基础操作的代码实现(C语言版)

因为堆的定义以及销毁、初始化很简单,就不赘述啦,直接看代码。难点主要在于堆的插入和删除,我们会用到两种方法向上调整法向下调整法,我会详细讲述。

1.定义堆

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* _arr;
	int _size;//有效数据个数
	int _capacity;//空间大小
}Heap;

2.堆的初始化

void HeapInit(Heap* hp)
{
	assert(hp);
	hp->_arr = NULL;
	hp->_capacity = hp->_size = 0;
}

3.堆的销毁

void HeapDestory(Heap* hp)
{
	assert(hp);
	if(hp->_arr) free(hp->_arr);
	hp->_arr = NULL;
	hp->_capacity = hp->_size = 0;
}

4.堆的插入

对于堆的插入我们可以分两种情况:
1.插入的结点是根结点,那么就直接hp->_arr[hp->_size] = x就行。
2.若插入的不是根节点,那么我们不仅要hp->_arr[hp->_size] = x,还需要进行向上调整
向上调整法(以小根堆为例,掌握啦小根堆大根堆也就会啦~):
其思想主要是将元素直接插入到最后一个位置,若不是根结点,则需要与其父结点进行比较,若比父结点小,则与父节点进行交换,一直重复该操作,直到孩子结点大于等于父结点或者到根结点。
为了方便柚柚们理解,我来为柚柚们讲一个例子:

6 5 4 3为例
第一次插入6的时候,为根节点,此时直接插入作为根结点,不需要调整,_size++。

第二次插入5的时候,此时5有父结点,其父节点序号为(1-1)/2 = 0,即为6,发现孩子结点比父结点小,我们就要把它们交换,交换之后让孩子结点指向序号为0的结点,此时为根节点不需要调整,插入完成,_size++。
在这里插入图片描述
第三次插入4,此时4有父结点,其父节点序号为(2-1)/2 = 0,即为5,发现孩子结点比父结点小,所以我们要把它们交换,交换之后让孩子结点指向序号为0的结点,此时为根节点不需要调整,插入完成,_size++。
在这里插入图片描述
第四次插入3,此时3有父结点,其父节点为(3-1)/2 = 1,即为6,发现孩子结点比父结点小,所以我们要把它们交换,交换之后让孩子结点指向序号为1的结点,然后再让1这个位置的结点与其父结点比较,其父结点为(1-1)/2 = 0,即为4,发现孩子结点比父结点大,我们就不需要再进行调整,插入完成,_size++。
在这里插入图片描述
整个过程就是这样,其实是很好理解,看完图应该就能够理解啦~

代码实现:

void Swap(int* x, int* y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}
//向上调整法
void AdjustUp(HPDataType* arr, int child)
{
	int parent = (child - 1) / 2;

	while (child > 0)//不需要等于,child只要走到根节点的位置,根节点没有父节点不需要交换
	{
		if (arr[child] < arr[parent])//若孩子结点比父结点小则交换
		{
			Swap(&arr[parent], &arr[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
//堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);

	if (hp->_capacity == hp->_size)
	{
		int newCapacity = hp->_capacity == 0 ? 4 : 2 * hp->_capacity;//分配空间,因为刚开始容量为0,所以要特殊处理
		HPDataType* tmp = (HPDataType*)realloc(hp->_arr,newCapacity * sizeof(HPDataType));
		if (tmp == NULL)  exit(1);//分配内存失败,结束程序
		hp->_arr = tmp;
		hp->_capacity = newCapacity;
	}
	hp->_arr[hp->_size] = x;

	AdjustUp(hp->_arr, hp->_size);//向上调整法
	
	hp->_size++;
}

5.堆的删除

对于堆的删除我们需要注意的是我们删除的是根结点,为了方便删除根节点,我们将根结点与最后一个结点进行交换,然后_size–,就把根节点删啦,但是此时打乱了堆的顺序,根结点可能就不是最小的啦,所以我们要对根节点进行向下调整。具体步骤就是,让交换之后的根结点与它的孩子结点比较,若比孩子结点大,则与孩子结点交换,然后让父节点指向该孩子结点,直到孩子结点的下标大于等于n(结点的个数)或者比其孩子结点都小;若比孩子结点们小,则结束,删除完成,其实理解了向上调整,向下调整就很容易理解啦,所以我就不再举例子啦。

//向下调整法
void AdjustDown(HPDataType* arr, int parent, int n)
{
	int child = parent * 2 + 1;//左孩子

	while (child < n)
	{
		//找左右孩子中找最小的
		if (child + 1 < n && arr[child] > arr[child + 1])
		{
			child++;
		}
		if (arr[child] < arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 + 1;

		}
		else
		{
			break;
		}
	}
}

void HeapPop(Heap* php)
{
	assert(php && php->_size);

	Swap(&php->_arr[0], &php->_arr[php->_size - 1]);

	--php->_size;

	AdjustDown(php->_arr, 0, php->_size);
}

6.取堆顶的数据

HPDataType HeapTop(Heap* php)
{
	assert(php && php->_size);

	return php->_arr[0];
}

7.堆的数据个数

int HeapSize(Heap* hp)
{
	return hp->_size;
}

8.堆的判空

bool HeapEmpty(Heap* php)
{
	assert(php);
	return php->_size == 0;
}

总结:

若是还没有理解向上调整法和向下调整法,柚柚们可以多看看代码多画画图,还有就是自己搞几个样例跟着程序调试,就可以搞懂啦~,日后还会更新堆排还有其它数据结构的知识,感兴趣的柚柚们可以三连,关注博主喔!

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

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

相关文章

Python开发环境配置(mac M2)

1. 前言 作为一名程序员&#xff0c;工作中需要使用Python进行编程&#xff0c;甚至因为项目需要还得是不同版本的Python如何手动管理多个版本的Python&#xff0c;如何给Pycharm&#xff08;IDE&#xff09;配置对应的interpreter等&#xff0c;都成为一个 “不熟练工” 的难…

【面向对象】设计模式概念和分类

零.前提提要 本文章是我考中级软件设计师时的笔记&#xff0c;基本都是一些自己的思路和见解&#xff0c;现记录一下&#xff0c;希望可以帮助到即将考证的同学。 一.面向对象设计模式的概念 二.面向对象的设计模式分类 设计模式确定了所包含的类和实例、他们的角色和写作方式以…

AMBER学习记录--使用Multiwfn计算有机小分子的RESP电荷--问题及解决

1 ORCAMultiwfn在wsl中的安装 ORCA的安装参考量子化学程序ORCA的安装方法 - 思想家公社的门口&#xff1a;量子化学分子模拟二次元 (sobereva.com) Multiwfn的安装 参考保姆级安装Linux版Multiwfn教程_multiwfn安装过程-CSDN博客 2 计算C3G的RESP电荷 2.1从pubchem上下载C3G的…

77. 组合【含回溯详解、N叉树类比、剪枝优化】

文章目录 77. 组合思路暴力法回溯与N叉树类比回溯法三部曲 总结剪枝优化剪枝总结 77. 组合 77. 组合 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&am…

spring loCDI 详解

文章目录 一、IoC & DI 基本知识1.1 IoC 的基本概念&#xff1a;1.2 IoC 的优势&#xff1a;1.3 DI 介绍&#xff1a; 二、IoC 详解2.1 Spring 容器&#xff1a;2.2 被存储 Bean 的命名约定&#xff1a;2.3 Bean 的存储方式&#xff1a;2.3.1 五大类注解&#xff1a;2.3.1.…

MySQL高阶2010-职员招聘人数2

目录 题目 准备数据 分析数据 总结 题目 一家公司想雇佣新员工。公司的工资预算是 $70000 。公司的招聘标准是&#xff1a; 继续雇佣薪水最低的高级职员&#xff0c;直到你不能再雇佣更多的高级职员。用剩下的预算雇佣薪水最低的初级职员。继续以最低的工资雇佣初级职员&…

linux文件编程_进程

1. 进程相关概念 面试中关于进程&#xff0c;应该会问的的几个问题&#xff1a; 1.1. 什么是程序&#xff0c;什么是进程&#xff0c;有什么区别&#xff1f; 程序是静态的概念&#xff0c;比如&#xff1a; 磁盘中生成的a.out文件&#xff0c;就叫做&#xff1a;程序进程是…

Linux常用语法

Linux常用语法 0.引言特殊路径符Linux 命令基础格式重要命令mkdir命令echo-tail命令 vi\vim编辑器的三种工作模式vi/vim简单介绍基础命令 运行模式命令模式下的快捷键 进程管理进程的命令 Linux解压缩tar格式zip命令unzip命令 ping,wget,curl等命令的使用Linux端口端口端口的划…

【算法篇】回溯算法类(1)(笔记)

目录 一、理论基础 1. 相关题目 2. 遍历过程 3. 代码框架 二、LeetCode 题目 1. 组合 2. 组合总和III 3. 电话号码的字母组合 4. 组合总和 5. 组合总和II 6. 分割回文串 7. 复原IP地址 8. 子集 一、理论基础 1. 相关题目 2. 遍历过程 3. 代码框架 void backtr…

光通信——APON/EPON/GPON/10G PON

目录 APON EPON GPON 上下行对称和非对称速率 OAM功能 汇聚子层 ATM封装方式 GEM封装方式 10G EPON EPON/GPON技术原理和特点 工作原理 关键技术 &#xff08;1&#xff09;测距、同步 &#xff08;2&#xff09;突发发送和接收 &#xff08;3&#xff09…

基于Word2Vec和LSTM实现微博评论情感分析

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…

【mmengine】优化器封装(OptimWrapper)(入门)优化器封装 vs 优化器

MMEngine 实现了优化器封装&#xff0c;为用户提供了统一的优化器访问接口。优化器封装支持不同的训练策略&#xff0c;包括混合精度训练、梯度累加和梯度截断。用户可以根据需求选择合适的训练策略。优化器封装还定义了一套标准的参数更新流程&#xff0c;用户可以基于这一套流…

SWAP、AquaCrop、FVCOM、Delft3D、SWAT、R+VIC、HSPF、HEC-HMS......

全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型&#xff0c;它综合考虑了土壤-水分-大气以及植被间的相互作用&#xff1b;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程&…

2024最新软件测试八股文(含答案+文档)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、软件测试基础面试题 1、阐述软件生命周期都有哪些阶段? 常见的软件生命周期模型有哪些? 软件生命周期是指一个计算机软件从功能确定设计&#xff0c;到…

系统安全 - Linux 安全模型及实践

文章目录 导图Linux 安全模型用户层权限管理的细节多用户环境中的权限管理文件权限与目录权限 最小权限原则的应用Linux 系统中的认证、授权和审计机制认证机制授权机制审计机制 主机入侵检测系统&#xff08;HIDS&#xff09;_ Host-based Intrusion Detection SystemHIDS 的概…

Android问题笔记五十:构建错误-AAPT2 aapt2-7.0.2-7396180-windows Daemon

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

jmeter中token测试

案例&#xff1a; 网站&#xff1a;http://shop.duoceshi.com 讲解&#xff1a;用三个接口来讲解 第一个接口code&#xff1a;GET http://manage.duoceshi.com/auth/code 第二个登录接口&#xff1a;http://manage.duoceshi.com/auth/login 第三个接口&#xff1a;http://…

iOS中的链表 - 双向链表

iOS中的链表 - 单向链表_ios 链表怎么实现-CSDN博客​​​​​​​ 引言 在数据结构中&#xff0c;链表是一种常见的且灵活的线性存储方式。与数组不同&#xff0c;链表的元素在内存中不必连续存储&#xff0c;这使得它们在动态内存分配时更加高效。其中&#xff0c;双向链表…

Pikachu-Cross-Site Scripting-DOM型xss_x

查看代码&#xff0c;输入的内容&#xff0c;通过get请求方式&#xff0c;用text 参数带过去&#xff1b; 获取text内容&#xff0c;赋值给xss 然后拼接到 dom 里&#xff1b;构造payload的关键语句&#xff1a; <a href"xss">就让往事都随风,都随风吧</a&…

【SQL】DDL语句

文章目录 1.SQL通用语法2.SQL的分类3.DDL3.1数据库操作3.2 表操作3.2.1 表操作--数据类型3.2.2 表操作--修改3.2.3 表操作--删除 SQL 全称 Structured Query Language&#xff0c;结构化查询语言。操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准 。…