堆的基本操作(c语言实现)

 1.堆的基本操作

1.1定义堆

typedef int HPDataType;//堆中存储数据的类型typedef struct Heap
{HPDataType* a;//用于存储数据的数组int size;//记录堆中已有元素个数int capacity;//记录堆的容量
}HP;

1.2初始化堆

然后我们需要一个初始化函数,对刚创建的堆进行初始化,注意在初始化期间要将传入数据建堆。

//初始化堆
void HeapInit(HP* php, HPDataType* a, int n)
{assert(php);HPDataType* tmp = (HPDataType*)malloc(sizeof(HPDataType)*n);//申请一个堆结构if (tmp == NULL){printf("malloc fail\n");exit(-1);}php->a = tmp;memcpy(php->a, a, sizeof(HPDataType)*n);//拷贝数据到堆中php->size = n;php->capacity = n;int i = 0;//建堆for (i = (php->size - 1 - 1) / 2; i >= 0; i--){AdjustDown(php->a, php->size, i);}
}

1.3 销毁堆

 为了避免内存泄漏,使用完动态开辟的内存空间后都要及时释放该空间,所以,一个用于释放内存空间的函数是必不可少的。

//销毁堆
void HeapDestroy(HP* php)
{assert(php);free(php->a);//释放动态开辟的数组php->a = NULL;//及时置空php->size = 0;//元素个数置0php->capacity = 0;//容量置0
}

1.4打印堆

 打印堆中的数据,这里用的打印格式是按照堆的物理结构进行打印,即打印为一排连续的数字。

//打印堆
void HeapPrint(HP* php)
{assert(php);//按照物理结构进行打印int i = 0;for (i = 0; i < php->size; i++){printf("%d ", php->a[i]);}printf("\n");
}

1.5堆的插入

数据插入时是插入到数组的末尾,即树形结构的最后一层的最后一个结点,所以插入数据后我们需要运用堆的向上调整算法对堆进行调整,使其在插入数据后仍然保持堆的结构。

void HeapPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * php->capacity*2);if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity *= 2;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}

 这个插入的效果完全取决于AdjustUp函数是给大堆设计的还是小堆!!

1.6堆的删除

堆的删除操作通常指的是从堆中移除最大值或最小值的操作。

在最大堆中,根节点是最大的元素,而在最小堆中,根节点是最小的元素。

以下是堆的删除操作的基本思路:

  1. 首先,将堆顶元素(即根节点)与最后一个元素交换位置,即将最大值或最小值移动到数组的末尾。
  2.  然后,将堆的大小减1,即删除了原来堆顶的元素。
  3. 最后,对新的堆顶元素进行向下调整,以保持堆的性质。在最大堆中,需要将新堆顶元素与其子节点中的较大者交换,直到满足最大堆的性质;在最小堆中,需要将新堆顶元素与其子节点中的较小者交换,直到满足最小堆的性质。

通过以上步骤,可以实现堆的删除操作,并保持堆的性质不变。

//堆的删除
void HeapPop(HP* php)
{assert(php);assert(!HeapEmpty(php));Swap(&php->a[0], &php->a[php->size - 1]);//交换堆顶和最后一个结点的位置php->size--;//删除最后一个结点(也就是删除原来堆顶的元素)AdjustDown(php->a, php->size, 0);//向下调整
}

这段代码是堆的删除操作,基本思路如下:

1. 首先,通过断言(assert)确保传入的堆指针(php)不为空,并且堆不为空。
2. 然后,将堆顶元素(索引为0的元素)与最后一个元素进行交换,即将堆顶元素移动到数组的末尾。
3. 接着,将堆的大小减1,即删除了原来堆顶的元素。
4. 最后,调用AdjustDown函数对新的堆顶元素进行向下调整,以保持堆的性质。

1.7.获取堆的数据个数

获取堆的数据个数,即返回堆结构体中的size变量。

//获取堆中数据个数
int HeapSize(HP* php)
{assert(php);return php->size;//返回堆中数据个数
}

1.8堆的判空

堆的判空,即判断堆结构体中的size变量是否为0。

//堆的判空
bool HeapEmpty(HP* php)
{assert(php);return php->size == 0;//判断堆中数据是否为0
}

2.完整操作加测试代码

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>typedef int HPDataType;
typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;
void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType x = *p1;*p1 = *p2;*p2 = x;
}//堆的向下调整(小堆)—— 左右子树都是小堆
void AdjustDown(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){// 选出左右孩子中大的那一个if (child + 1 < n && a[child + 1] < a[child]){++child;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
//初始化堆
void HeapInit(HP* php, HPDataType* a, int n)
{assert(php);HPDataType* tmp = (HPDataType*)malloc(sizeof(HPDataType) * n);//申请一个堆结构if (tmp == NULL){printf("malloc fail\n");exit(-1);}php->a = tmp;memcpy(php->a, a, sizeof(HPDataType) * n);//拷贝数据到堆中php->size = n;php->capacity = n;int i = 0;//建堆for (i = (php->size - 1 - 1) / 2; i >= 0; i--){AdjustDown(php->a, php->size, i);}
}bool HeapEmpty(HP* php)
{assert(php);return php->size == 0;
}
void HeapDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->capacity = php->size = 0;
}//堆的向上调整(小堆)
void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (child > 0)//调整到根结点的位置截止{if (a[child] < a[parent])//孩子结点的值小于父结点的值{//将父结点与孩子结点交换Swap(&a[child], &a[parent]);//继续向上进行调整child = parent;parent = (child - 1) / 2;}else//已成堆{break;}}
}void HeapPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * php->capacity * 2);if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity *= 2;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}//打印堆
void HeapPrint(HP* php)
{assert(php);//按照物理结构进行打印int i = 0;for (i = 0; i < php->size; i++){printf("%d ", php->a[i]);}printf("\n");
}void HeapPop(HP* php)
{assert(php);assert(!HeapEmpty(php));// 删除数据Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a, php->size, 0);
}HPDataType HeapTop(HP* php)
{assert(php);return php->a[0];
}int HeapSize(HP* php)
{assert(php);return php->size;
}
int main()
{HP hp;int a[] = { 4,18,42,12,21,3,5,5,88,5,5,15,5,45,5 };int size = sizeof(a) / sizeof(a[0]);HeapInit(&hp,a,size);HeapPrint(&hp);HeapPop(&hp);HeapPrint(&hp);HeapPush(&hp, 4);HeapPrint(&hp);return 0;
}

我们可以来验证一下是不是堆

  1. 堆的向上调整和向下调整的代码一定要是匹配的,小堆的只能和小堆匹配使用,大堆的只能和大堆匹配使用,要不然就会让你十分抓马 ,我就是因为错误匹配使用就导致了痛苦了两个晚上……
  2. 还有就是大家一定要去画图去验证一下这个是不是堆,不要用眼睛看
  3. 其次就是一定要建好堆后再使用堆的向上调整和向下调整

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Element-plus修改input的placeholder文字颜色

需求 代码 .el-input__inner::placeholder {color: #666f8d !important; }

vs 2022 Xamarin 生成 Android apk

再保存&#xff0c;如果没有生成apk就重启软件 再试一次

软件测试小妙招:详细解读 postman接口测试导入导出操作

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 postman中的集合脚本&#xff0c;环境变量、全局变量全部都可以导出&#xff0c;然后分享给团队…

Python开源工具库使用之运动姿势追踪库mediapipe

文章目录 前言一、姿势估计1.1 姿态关键点1.2 旧版 solution API1.3 新版 solution API1.4 俯卧撑计数 二、手部追踪2.1 手部姿态2.2 API 使用2.3 识别手势含义 参考 前言 Mediapipe 是谷歌出品的一种开源框架&#xff0c;旨在为开发者提供一种简单而强大的工具&#xff0c;用…

三.搜索与图论(未完结)

DFS(深搜) 之前写过三篇关于dfs的 练习总结: 基础算法--递归搜索DFS练习总结(上)-CSDN博客 基础算法--递归搜索DFS练习总结(中)-CSDN博客 基础算法--递归搜索DFS练习总结(下)-CSDN博客 以下题目均为 补充练习: P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins …

【华为】AC直连二层组网隧道转发实验配置

【华为】AC直连二层组网隧道转发实验配置 实验需求拓扑配置AC数据规划表 AC的配置顺序AC1基本配置(二层通信)AP上线VAP组关联--WLAN业务流量 LSW1AR1STA获取AP的业务流量 配置文档 实验需求 AC组网方式&#xff1a;直连二层组网。 业务数据转发方式&#xff1a;隧道转发。 DHC…

MacOS搭建docker本地私有镜像库

相关环境 macOS: bigsur 11.7.8 docker desktop: 4.22.0 docker engine: 24.0.5 准备工作 本机已经安装好docker desktop&#xff0c;未安装的自行参考其他教程。如果不能翻墙&#xff0c;可以修改本地的镜像地址&#xff0c;可在docker desktop 设置中的docker engine中修…

Excel Module: Iteration #1 EasyExcel生成下拉列表模版时传入动态参数查询下拉数据

系列文章 EasyExcel生成带下拉列表或多级级联列表的Excel模版自定义校验导入数据(修订) 目录 系列文章前言仓库一、实现1.1 下拉元数据对象1.2 构建下拉元数据的映射关系1.3 框架方式1.3.1 框架实现1.3.2 框架用例模版类加载下拉业务导出接口 1.4 EasyExcel方式1.4.1 EasyExce…

Redis(Jedis和SpringBoot整合Redis)

文章目录 1.Jedis1.介绍2.环境配置1.创建maven项目2.pom.xml引入依赖3.新建一个包并创建一个文件 3.Jedis远程连接到Redis1.Redis放到服务器可以连接的前提条件2.为Redis设置密码1.编辑配置文件2.找到 requirepass3.设置密码为root4.重启Redis&#xff0c;在shutdown的时候报错…

计算机网络——Dijkstra路由算法

实验目的 实现基于 Dijkstra 算法的路由软件 实验内容 网络拓扑如图所示 实验过程 先编写开辟应该图的空间&#xff0c;然后给点映射数字&#xff0c;构建图。程序获取用户输入的学号&#xff0c;构建图中边的权值。接下来程序从用户输入获取最短路径的搜索起点&#xff0…

基于C++基础的函数模块

在C中&#xff0c;函数是一段封装了某种功能的代码块&#xff0c;可以在程序的不同地方重复使用。函数定义包含如下组成部分&#xff1a; 函数头&#xff1a;函数头包括函数返回类型、函数名和参数列表。函数返回类型规定了函数返回的数据类型&#xff0c;函数名是函数的唯一标…

Java_从入门到JavaEE_11

一、抽象类及抽象方法 1.认识抽象类及抽象方法 应用场景&#xff1a;当一个方法必须在父类中出现&#xff0c;但是这个方法又不好实现&#xff0c;就把该方法变成抽象方法&#xff0c;交给非抽象的子类去实现 实例&#xff1a; //抽象类 public abstract class 类名{//抽象方…

5月将有17款游戏发布,腾讯的《地下城与勇士:起源》备受关注

易采游戏网5月8日消息&#xff0c;本月将有17款新游戏预计上线&#xff0c;其中14款已正式定档&#xff0c;游戏市场即将迎来一场盛大的狂欢。在众多备受期待的游戏中&#xff0c;有两款游戏尤其引人注目&#xff0c;它们分别是来自库洛和腾讯的《地下城与勇士&#xff1a;起源…

学习方法的重要性

原贴&#xff1a;https://www.cnblogs.com/feily/p/13999204.html 原贴&#xff1a;https://36kr.com/p/1236733055209095 1、 “一万小时定律”的正确和误区 正确&#xff1a; 天才和大师的非凡&#xff0c;不是真的天资超人一等&#xff0c;而是付出了持续不断的努力&…

武汉星起航:成功挂牌上股交,优势尽显启新程,共绘创业投资梦

在金秋十月的尾声&#xff0c;武汉星起航电子商务有限公司迎来了一个重要的历史时刻——于2023年10月30日在上海股权托管交易中心成功挂牌展示&#xff0c;正式登陆资本市场。这一里程碑式的跨越&#xff0c;不仅标志着武汉星起航在跨境电商领域的卓越实力&#xff0c;更彰显了…

MAC地址冲突案例

1、问题描述&#xff1a;WiFi-A网段做了策略路由&#xff0c;引流到另一台设备&#xff0c;连接WiFi-A后通过DHCP获取到了地址却无法上网&#xff0c;此时排查思路是什么&#xff1f; &#xff08;1&#xff09;、排查方法&#xff1a; 看到网关通信是否正常 第一次获取地址正…

mysql中varchar与bigint直接比较会导致精度丢失以至于匹配到多行数据

在mysql中&#xff0c;我们都知道如果一个索引字段使用了函数或者计算那么查询的时候索引会失效&#xff0c;可是我相信在联表的时候我们只会关注两个表关联字段是否都创建了索引&#xff0c;却没有关注过这两个字段的类型是否一致&#xff0c;如果不一致的话索引是会失效的&am…

Windows系统完全卸载删除 Node.js (包含控制面板找不到node.js选项情况)

1.打开cmd命令行窗口&#xff0c;输入npm cache clean --force 回车执行 2.打开控制面板&#xff0c;在控制面板中把Node.js卸载 移除之后检查环境变量是否也移除&#xff1a;点击Path&#xff0c;点击编辑。 把环境变量中和node有关的全部移除&#xff0c;然后点击确定。 3.重…

WPF之创建无外观控件

1&#xff0c;定义无外观控件。 定义默认样式&#xff0c;在其静态构造函数中调用DefaultStyleKeyProperty.OverrideMetadata()。 //设置默认样式DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker))); 在项目…

Android C++ 开发调试 LLDB 工具的使用

文章目录 调试环境准备基础命令Breakpoint CommandsWatchpoint CommandsExamining VariablesEvaluating ExpressionsExamining Thread StateExecutable and Shared Library Query Commands 参考&#xff1a; Android 中在进行 NDK 开发的时候&#xff0c;我们经常需要进行 C 代…