数据结构:堆的实现(C实现)

个人主页 : 个人主页
个人专栏 : 《数据结构》 《C语言》
文章目录
- 一、堆
- 二、实现思路
- 1. 结构的定义
- 2. 堆的构建 (HeapInit)
- 3. 堆的销毁 (HeapDestroy)
- 4. 堆的插入 (HeapPush)
- 5. 堆的删除 (HeapPop)
- 6. 取堆顶的数据 (HeapTop)
- 7. 堆的数据个数 (HeapSize)
- 8. 堆的判空 (HeapEmpty)
- 三、代码实现
- 总结
一、堆
当一颗完全二叉树用顺序表来存储时,其被称为堆。
- 堆总是一棵完全二叉树
- 堆的某个节点的值总是不大于(大堆)或不小于(小堆)其父节点的值
其可以被用来解决top k 问题 或 堆排序

下面就是要实现的堆的功能 重点在于堆的插入 和 堆的删除
//堆的构建
void HeapInit(Heap* hp);//堆的销毁
void HeapDestroy(Heap* hp);//堆的插入
void HeapPush(Heap* hp, HPDataType x);//堆的删除
void HeapPop(Heap* hp);//取堆顶的数据
HPDataType HeapTop(Heap* hp);//堆的数据个数
int HeapSize(Heap* hp);//堆的判空
bool HeapEmpty(Heap* hp);
二、实现思路
下部分的图,都以逻辑结构为主!!!
这里构建的是小堆。
1. 结构的定义
堆就是用顺序表来存储一颗完全二叉树,那么堆的结构就与顺序表的结构相同。
一个指向动态开辟空间的指针(data),一个变量记录空间大小(capacity),一个变量记录空间中有效数据(size)。
typedef int HPDataType;typedef struct Heap
{HPDataType* data;int capacity;int size;
}Heap;
2. 堆的构建 (HeapInit)
malloc一块空间,用data记录其地址,capacity记录此时空间大小,size置0(此时空间内无有效数据)。
//堆的构建
#define SIZE 4void HeapInit(Heap* hp)
{assert(hp);hp->data = (HPDataType*)malloc(sizeof(HPDataType) * SIZE);if (hp == NULL) {perror("mallo: ");exit(-1);}hp->capacity = SIZE;hp->size = 0;
}
3. 堆的销毁 (HeapDestroy)
free掉动态开辟的空间,使capacity 和 size 置 0(此时空间大小为0)
//堆的销毁
void HeapDestroy(Heap* hp)
{assert(hp);free(hp->data);hp->data = NULL;hp->capacity = hp->size = 0;
}
4. 堆的插入 (HeapPush)
将数据插入到堆的尾部(最后一个子节点后),然后与其父节点相比较,如果该节点小于其父节点(这里是小堆),交换两个节点的值,直到该节点为堆顶或其父节点小于该节点。
- 假设该节点下标是 i,那么其父节点的小标是 ( i - 1 ) / 2

//交换
void swap(HPDataType* a, HPDataType* b)
{HPDataType tmp = *a;*a = *b;*b = tmp;
}//向上调整 假设该节点是 i,父节点是 (i - 1) / 2
void AdjustUp(HPDataType* data, int child)
{int parent = (child - 1) / 2;while (child > 0){if (data[child] < data[parent]){swap(&data[child], &data[parent]);child = parent;parent = (child - 1) / 2;}else {break;}}
}//堆的插入
void HeapPush(Heap* hp, HPDataType x)
{assert(hp);//检查容量if (hp->capacity == hp->size){HPDataType* tmp = (HPDataType*)realloc(hp->data ,sizeof(HPDataType) * (hp->capacity * 2));if (tmp == NULL){perror("realloc:");exit(-1);}hp->data = tmp;hp->capacity *= 2;}hp->data[hp->size] = x;hp->size++;//向上调整 传入数组和出入数据的下标//此处是小堆AdjustUp(hp->data, hp->size - 1);
}
5. 堆的删除 (HeapPop)
堆的删除是删除堆顶数据。
堆顶数据和堆的尾部数据交换,size 减一,然后将新的堆顶数据与其左右孩子节点的最小值比较,如果新堆顶数据大于左右孩子节点的最小值,交换数据,再次与新的左右孩子节点的最小值
比较。直到该数据小于左右孩子的最小值,或该数据超出有效数据范围。
- 假设某个节点的下标是 i,其左孩子节点的下标:i * 2 + 1,其右孩子的下标:i * 2 + 2
- 删除堆顶数据,不能挪到数据将堆顶数据覆盖。如果挪到数据,那么兄弟节点可能会变成父子节点,而兄弟节点之间并不保证大小关系,可能会破坏堆的结构(这里是会破坏小堆结构)。

//交换
void swap(HPDataType* a, HPDataType* b)
{HPDataType tmp = *a;*a = *b;*b = tmp;
}//向下调整,假设该节点是 i, 右孩子节点是 2 * i + 1,左孩子节点是 2 * i + 2
void AdjustDown(HPDataType* data, int parent, int size)
{int child = parent * 2 + 1;while (parent < size){//防止越界 找左右孩子中最小的if (child + 1 < size && data[child] > data[child + 1]){child++;}if (child < size && data[parent] > data[child]){swap(&data[parent], &data[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}//堆的删除 首元素 与 尾元素交换,新的堆顶在向下调整
void HeapPop(Heap* hp)
{assert(hp);assert(!HeapEmpty(hp));hp->data[0] = hp->data[hp->size - 1];hp->size--;//向下调整AdjustDown(hp->data, 0, hp->size);
}
6. 取堆顶的数据 (HeapTop)
读取数组空间下标为0处即可。
//取堆顶的数据
HPDataType HeapTop(Heap* hp)
{assert(hp);return hp->data[0];
}
7. 堆的数据个数 (HeapSize)
堆的结构中size表示此时堆中有效数据的个数,访问size即可。
//堆的数据个数
int HeapSize(Heap* hp)
{assert(hp);return hp->size;
}
8. 堆的判空 (HeapEmpty)
size表示堆的有效数据个数,如果size == 0,表示堆为空。
//堆的判空
bool HeapEmpty(Heap* hp)
{assert(hp);return hp->size == 0;
}
三、代码实现
//Heap.c 文件#include "Heap.h"//堆的构建
void HeapInit(Heap* hp)
{assert(hp);hp->data = (HPDataType*)malloc(sizeof(HPDataType) * SIZE);if (hp == NULL) {perror("mallo: ");exit(-1);}hp->capacity = SIZE;hp->size = 0;
}//堆的销毁
void HeapDestroy(Heap* hp)
{assert(hp);free(hp->data);hp->data = NULL;hp->capacity = hp->size = 0;
}//交换
void swap(HPDataType* a, HPDataType* b)
{HPDataType tmp = *a;*a = *b;*b = tmp;
}//向上调整 假设该节点是 i,父节点是 (i - 1) / 2
void AdjustUp(HPDataType* data, int child)
{int parent = (child - 1) / 2;while (child > 0){if (data[child] < data[parent]){swap(&data[child], &data[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}//堆的插入
void HeapPush(Heap* hp, HPDataType x)
{assert(hp);//检查容量if (hp->capacity == hp->size){HPDataType* tmp = (HPDataType*)realloc(hp->data ,sizeof(HPDataType) * (hp->capacity * 2));if (tmp == NULL){perror("realloc:");exit(-1);}hp->data = tmp;hp->capacity *= 2;}hp->data[hp->size] = x;hp->size++;//向上调整 传入数组和出入数据的下标//此处是小堆AdjustUp(hp->data, hp->size - 1);
}//向下调整,假设该节点是 i, 右孩子节点是 2 * i + 1,左孩子节点是 2 * i + 2
void AdjustDown(HPDataType* data, int parent, int size)
{int child = parent * 2 + 1;while (parent < size){//防止越界 找左右孩子中最小的if (child + 1 < size && data[child] > data[child + 1]){child++;}if (child < size && data[parent] > data[child]){swap(&data[parent], &data[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}//堆的删除 首元素 与 尾元素交换,新的堆顶在向下调整
void HeapPop(Heap* hp)
{assert(hp);assert(!HeapEmpty(hp));hp->data[0] = hp->data[hp->size - 1];hp->size--;//向下调整AdjustDown(hp->data, 0, hp->size);
}//取堆顶的数据
HPDataType HeapTop(Heap* hp)
{assert(hp);return hp->data[0];
}//堆的数据个数
int HeapSize(Heap* hp)
{assert(hp);return hp->size;
}//堆的判空
bool HeapEmpty(Heap* hp)
{assert(hp);return hp->size == 0;
}
//Heap.h 文件#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>#define SIZE 4typedef int HPDataType;typedef struct Heap
{HPDataType* data;int capacity;int size;
}Heap;//堆的构建
void HeapInit(Heap* hp);//堆的销毁
void HeapDestroy(Heap* hp);//堆的插入
void HeapPush(Heap* hp, HPDataType x);//堆的删除
void HeapPop(Heap* hp);//取堆顶的数据
HPDataType HeapTop(Heap* hp);//堆的数据个数
int HeapSize(Heap* hp);//堆的判空
bool HeapEmpty(Heap* hp);
总结
以上就是我对于堆的实现!!!

相关文章:
数据结构:堆的实现(C实现)
个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》 文章目录 一、堆二、实现思路1. 结构的定义2. 堆的构建 (HeapInit)3. 堆的销毁 (HeapDestroy)4. 堆的插入 (HeapPush)5. 堆的删除 (HeapPop)6. 取堆顶的数据 (HeapTop)7. 堆的数据个数 (HeapSize…...
数据分析两件套ClickHouse+Metabase(一)
ClickHouse篇 安装ClickHouse ClickHouse有中文文档, 安装简单 -> 文档 官方提供了四种包的安装方式, deb/rpm/tgz/docker, 自行选择适合自己操作系统的安装方式 这里我们选deb的方式, 其他方式看文档 sudo apt-get install -y apt-transport-https ca-certificates dirm…...
urllib爬虫模块
urllib爬取数据 import urllib.request as request# 定义url url "https://www.baidu.com" #模拟浏览器发起请求获取响应对象 response request.urlopen(url)""" read方法返回的是字节形式的二进制数据 二进制--》字符串 解码 decode( 编码的格式…...
TCP消息传输可靠性保证
TCP链接与断开 -- 三次握手&四次挥手 三次握手 TCP 提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好两端之间的准备工作。 所谓三次握手是指建立一个 TCP 连接时需要客户端和服务器端总共发送三个包以确认连接的建立。在socket编程中,这一…...
Visual Studio 与QT ui文件
对.ui文件鼠标右键,然后单击 Open with…在弹出的窗口中,选中左侧的 Qt Designer,然后单击右侧的 Add 按钮,随后会弹出一个窗口,在 Program: 输入框中输入 Qt Designer 的路径,最后单击 OK找到 Qt Designer…...
竞赛项目 深度学习验证码识别 - 机器视觉 python opencv
文章目录 0 前言1 项目简介2 验证码识别步骤2.1 灰度处理&二值化2.2 去除边框2.3 图像降噪2.4 字符切割2.5 识别 3 基于tensorflow的验证码识别3.1 数据集3.2 基于tf的神经网络训练代码 4 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 &#x…...
ORA-00845: MEMORY_TARGET not supported on this system
处理故障时,发现startup实例失败,报错ORA-00845: MEMORY_TARGET not supported on this system SYSorcl1> startup; ORA-00845: MEMORY_TARGET not supported on this system 查看alert日志,报错如下 Starting ORACLE instance (normal…...
wps设置一键标题字体和大小
参考 wps设置一键标题字体和大小:https://www.kafan.cn/A/7v5le1op3g.html 统一一键设置...
TIA博途WINCC_如何在IO域中保证输入数值只能为正数?
TIA博途WINCC_如何在IO域中保证输入数值只能为正数? 在某些情况下,输入的数值受到限制,本例就以输入的数值必须为正整数为例进行说明。 如下图所示,在PLC的全局DB块中添加一个测试变量,数据类型为Int(该数据类型的范围为-32768~+32767), 如下图所示,将该测试变量拖拽到…...
《Linux从练气到飞升》No.13 Linux进程状态
🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的…...
安卓快速开发
1.环境搭建 Android Studio下载网页:https://developer.android.google.cn/studio/index.html 第一次新建工程需要等待很长时间,新建一个Empty Views Activity 项目,右上角选择要运行的机器,运行就安装上去了(打开USB调试)。 2…...
SpringCloud微服务之间如何进行用户信息传递(涉及:Gateway、OpenFeign组件)
目录 1、想达到的效果2、用户信息在微服务之间传递的两种途径3、用RuoYi-Cloud为例进行演示说明(1)网关将用户信息写在请求头中(2)业务微服务之间通过OpenFeign进行调用,并且将用户信息写在OpenFeign准备的请求头中&am…...
RabbitMQ之TTL+死信队列实现延迟队列
RabbitMQ是一个流行的消息队列系统,它提供了许多有用的功能,其中之一是TTL(Time To Live)和死信队列。这些功能可以用来实现延迟队列,让我们来看看如何使用它们。 首先,什么是TTL?TTL是消息的存…...
GrapeCity Documents for PDF (GcPdf) 6.2 Crack
GrapeCity PDF 文档 (GcPdf) 改进了对由 GcPdf 以外的软件生成的现有 PDF 文档的处理 在新的 v6.2 版本中,GcPdf 增强了 PDF 文档的加载和保存,并提供以下优势: GcPdf 现在可以加载和保存可能不严格符合 PDF 规范的 PDF 文档。GcPdf 现在将…...
【Sklearn】基于随机森林算法的数据分类预测(Excel可直接替换数据)
【Sklearn】基于随机森林算法的数据分类预测(Excel可直接替换数据) 1.模型原理1.1 模型原理1.2 数学模型2.模型参数3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果1.模型原理 随机森林(Random Forest)是一种集成学习方法,通过组合多个决策树来构建强大的分类或回归…...
问AI一个严肃的问题
chatgpt的问世再一次掀起了AI的浪潮,其实我一直在想,AI和人类的关系未来会怎样发展,我们未来会怎样和AI相处,AI真的会完全取代人类吗,带着这个问题,我问了下chatgpt,看一看它是怎么看待这个问题…...
Flowable流程的挂起与激活详解
1. 挂起与激活的定义及区别 在Flowable流程中,挂起是指将流程实例暂停,它将停止执行当前步骤并暂时中断流程的执行。相反,激活是指恢复被挂起的流程实例的执行,使其能够继续执行后续步骤。 区别在于挂起流程实例后,流…...
探索前端动画之CSS魔法
引言 在现代网页设计中,动画已经成为了吸引用户注意力、提升用户体验的重要手段之一。而在前端开发中,CSS动画是一种常见且强大的实现方式。本篇博客将带你深入探索前端动画中的CSS魔法,通过清晰的思路和完整的示例代码,帮助你掌…...
Oracle数据库登录遇到密码临期问题
在oracle数据库中,如果设置了密码的有效期,则会出现密码临期提醒的问题,默认的密码有效期是180天,默认的密码提醒时间是15天(此处缺乏官方文档支撑),在密码临近过期时,如果登录 Orac…...
LVGL学习笔记 30 - List(列表)
目录 1. 添加文本 2. 添加按钮 3. 事件 4. 修改样式 4.1 背景色 4.2 改变项的颜色 列表是一个垂直布局的矩形,可以向其中添加按钮和文本。 lv_obj_t* list1 lv_list_create(lv_scr_act());lv_obj_set_size(list1, 180, 220);lv_obj_center(list1); 部件包含&…...
React Native Interactable终极指南:TouchesInside与静态交互对比详解
React Native Interactable终极指南:TouchesInside与静态交互对比详解 【免费下载链接】react-native-interactable Experimental implementation of high performance interactable views in React Native 项目地址: https://gitcode.com/gh_mirrors/re/react-na…...
2025_NIPS_JavisGPT: A Unified Multi-modal LLM for Sounding-Video Comprehension and Generation
JavisGPT 论文核心总结与翻译 一、主要内容总结 JavisGPT 是首个面向同步音视频(sounding video)理解与生成的统一多模态大语言模型(MLLM),核心解决现有模型将音视频视为独立模态、缺乏时空同步建模的问题。 模型采用编码器-LLM-解码器架构,以 Qwen2.5-VL-7B-Instruct…...
BIOS更新全攻略:从版本检查到安全升级的实用指南
1. BIOS更新前的必要准备 每次打开电脑时,那个一闪而过的黑底白字界面就是BIOS(基本输入输出系统),它就像是电脑硬件的"总指挥"。我见过太多人因为盲目刷BIOS导致主板报废的案例,所以更新前一定要做好这些准…...
ARM单片机位带操作原理与应用详解
1. ARM单片机位带操作基础回顾在嵌入式开发中,位带操作(Bit-Banding)是Cortex-M系列处理器提供的一个非常实用的功能特性。简单来说,它允许开发者通过访问特定内存地址的方式,直接操作某个寄存器的单个比特位,而无需进行传统的&qu…...
直方图均衡化:从理论到实践——MATLAB代码实现与效果对比
1. 直方图均衡化基础概念 直方图均衡化是数字图像处理中最基础也最实用的技术之一。简单来说,它就像给照片做了一次"智能美颜",能够自动调整图像的对比度,让暗部更清晰、亮部更细腻。想象一下你拍摄了一张背光的人像照片࿰…...
history 常见优化配置
文章目录 一、写在哪个文件生效?(关键) ✅ Bash 环境下生效位置(最常见) 1️⃣ 全局生效(所有用户) ✅ 推荐方式(最规范) 2️⃣ 全局兜底(老系统) 3️⃣ 当前用户生效 ✅ 各文件加载顺序(很重要) 二、不同场景推荐配置位置 三、验证是否生效 四、一句话总结(运维…...
白嫖DeepSeek、GLM、MiniMax、Kimi等大模型,每天 1亿 Token 免费领!
每天免费领 1亿 Token,白嫖DeepSeek、GLM、MiniMax、Kimi等大模型! 最近折腾 AI 编程的朋友估计挺多的。这玩意儿现在进化得确实有点吓人。就拿名气最大的 Claude Code 来说,它这个命令行工具直接把写代码变成了“在线聊天”。你只要嘴上说清…...
SEO优化师如何制定优化策略和计划_SEO优化师如何分析网站流量和排名数据
SEO优化师如何制定优化策略和计划_SEO优化师如何分析网站流量和排名数据 前言 SEO(搜索引擎优化)在现代数字营销中扮演着至关重要的角色。对于一个SEO优化师来说,制定有效的优化策略和计划是关键,分析网站流量和排名数据能帮助他…...
交付验收前批量筛一遍配图质量:桌面工具用法记录
如果你经常遇到这种场景:项目交付包里附带大量截图、现场照片,甲方要求「明显糊的、过曝的别混进来」,但文件夹嵌套很深,人工抽查像抽奖。可以试一款只做「打分按档归类」的 Windows 桌面工具,全称【批量图片质量检测筛…...
论文AI率80%+的紧急处理方案,答辩前用得上
距离答辩3天,AI率检出80%——这是最糟糕的时间点碰到最糟糕的问题。 不要慌,这个情况有成熟的处理方案,我见过很多人在这个时间节点成功降下来的。下面是紧急情况下的处理方法,按照时间紧迫程度分了几个场景。 先做一个判断&…...
