【数据结构与算法】堆的实现(附源码)
目录
一.堆的概念及结构
二.接口实现
A.初始化 Heapinit 销毁 Heapdestroy
B.插入 Heappush 向上调整 AdjustUp
1.Heappush
2.AdjustUp
C.删除 Heappop 向下调整 AdjustDown
D.堆的判空 Heapempty 堆顶数据 Heaptop 堆的大小 Heapsize
三.源码
Heap.h
Heap.c
test.c
一.堆的概念及结构
1.概念
如果有一个关键码的集合K = { , , ,…, },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: <= 且 <= ( >= 且 >= ) i = 0,1,2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
2.堆的性质:
A.堆中某个节点的值总是不大于或不小于其父节点的值;
B.堆总是一棵完全二叉树。
其实堆是一种二叉树,通常我们都是用数据表实现,也就是说堆的底层是数组,数组中的小标表示二叉树的节点,所以在实现堆之前,我们有必要了解完全二叉树中节点之间的关系。
1.理解父节点 parent 和子节点 child;
2.了解父节点与子节点之间的关系:
A.parent=(child-1)/2;
B.左孩子child=2*parent+1;
C.右孩子child=2*parent+2。
二.接口实现
A.初始化 Heapinit 销毁 Heapdestroy
这里的初始化和销毁都很简单,相信这对学到堆的人并不是什么难事,和顺序表的操作是一样的,如果实在不理解的话,请看 -> 顺序表
B.插入 Heappush 向上调整 AdjustUp
1.Heappush
插入数据很简单,直接对数组赋值,然后 size 再加加就行了,但是在插入完数据后,我们得保证它是堆,所以这就需要用到向上调整这个函数。
2.AdjustUp
假设我们建的是大堆,我们将新插入的节点与它的父节点比较:
1.如果比它的父节点大,则与其交换,所以交换后的父节点就成为了子节点,再与其父节点比较,以此类推;
2.如果child<=0 则结束循环。
void Swap(HPdatatype* p1, HPdatatype* p2) //交换函数
{HPdatatype tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPdatatype* arr, int child) //向上调整
{assert(arr);int parent = (child - 1) / 2;while (child > 0){if (arr[child] > arr[parent]){Swap(&arr[child], &arr[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}void Heappush(Heap* php, HPdatatype x)
{assert(php);if (php->size == php->capacity){HPdatatype* tmp = (HPdatatype*)realloc(php->arr, 2 * sizeof(HPdatatype) * php->capacity);if (tmp == NULL){perror("realloc fail");exit(-1);}php->arr = tmp;php->capacity *= 2;}php->arr[php->size] = x;php->size++;AdjustUp(php->arr, php->size - 1); //注意这里要传size-1,因为size表示的是下一个位置
}
C.删除 Heappop 向下调整 AdjustDown
1.删除的话,我们是要删除堆顶的数据,因为删除堆尾的数据并没有什么实际意义,删除就是让size--,但是堆顶数据的下标是0,所以在删除前应先交换堆顶和堆尾的数据;
2.删除完后,还要保持它还是个堆,不能把后面的顺序搞乱了,要想达到这个目的,就需要使用到向下调整这个函数;
3.假设是大堆,向下调整是父节点与其较大的子节点比较,如果较大的那个子节点大于父节点,则二者交换,然后较大的子节点成为了新的父节点,当子节点的下标大于或是等于节点总数,也就是size时,就结束循环。
D.堆的判空 Heapempty 堆顶数据 Heaptop 堆的大小 Heapsize
这些接口的实现都非常简单,博主就不在这里讲述了,可以参考后面的源码。
三.源码
Heap.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <time.h>#define MAX_MIN < //通过改变这里的符号,可以决定是建大堆还是小堆typedef int HPdatatype;typedef struct Heap
{HPdatatype* arr;int size;int capacity;
}Heap;void Heapinit(Heap* php);void Swap(HPdatatype* p1, HPdatatype* p2);void AdjustUp(HPdatatype* arr, int child); //向上调整void Heappush(Heap* php, HPdatatype x);void AdjustDown(HPdatatype* arr, int parent, int n); //向下调整void Heappop(Heap* php);HPdatatype Heaptop(Heap* php);int Heapsize(Heap* php);bool Heapempty(Heap* php);void Heapdestroy(Heap* php);
Heap.c
#include "Heap.h"void Heapinit(Heap* php)
{assert(php);php->arr = (HPdatatype*)malloc(sizeof(HPdatatype) * 4);if (php->arr == NULL){perror("malloc fail");exit(-1);}php->size = 0;php->capacity = 4;
}void Swap(HPdatatype* p1, HPdatatype* p2)
{HPdatatype tmp = *p1;*p1 = *p2;*p2 = tmp;
}///Сvoid AdjustUp(HPdatatype* arr, int child)
{assert(arr);int parent = (child - 1) / 2;while (child > 0){if (arr[child] MAX_MIN arr[parent]){Swap(&arr[child], &arr[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}void Heappush(Heap* php, HPdatatype x)
{assert(php);if (php->size == php->capacity) //插入前,判断数组是否已满{HPdatatype* tmp = (HPdatatype*)realloc(php->arr, 2 * sizeof(HPdatatype) * php->capacity);if (tmp == NULL){perror("realloc fail");exit(-1);}php->arr = tmp;php->capacity *= 2;}php->arr[php->size] = x;php->size++;AdjustUp(php->arr, php->size - 1); //这里要传size-1
}void AdjustDown(HPdatatype* arr, int parent, int n)
{assert(arr);int child = 2 * parent + 1;while (child < n){//判断较大(较小)的子节点if ((child + 1) < n && arr[child + 1] MAX_MIN arr[child]) {child++;}if (arr[child] MAX_MIN arr[parent]){Swap(&arr[child], &arr[parent]);parent = child;child = 2 * parent + 1;}elsebreak;}
}void Heappop(Heap* php)
{assert(php);assert(php->size);Swap(&php->arr[0], &php->arr[php->size - 1]);php->size--;AdjustDown(php->arr, 0, php->size);
}HPdatatype Heaptop(Heap* php)
{assert(php);assert(php->size); //为空时不能取数据return php->arr[0];
}int Heapsize(Heap* php)
{assert(php);return php->size;
}bool Heapempty(Heap* php)
{assert(php);return php->size == 0; //size==0即为空
}void Heapdestroy(Heap* php)
{assert(php);free(php->arr);php->arr = NULL;php->size = 0;php->capacity = 0;
}
test.c
#include "Heap.h"void testHeap()
{Heap hp;Heapinit(&hp);int i = 0, n = 10;int x = 0;while (n){x = rand() % 100 + 1;Heappush(&hp, x);n--;}while (!Heapempty(&hp)){printf("%d ", Heaptop(&hp));Heappop(&hp);}printf("\n");Heapdestroy(&hp);
}int main()
{srand((unsigned int)time(NULL));testHeap();return 0;
}
🐲👻这循环队列的讲解就到这里了,若有错误或是建议欢迎小伙伴们指出。🐯🤖
🥰🤩希望小伙伴们可以多多支持博主哦。😍😃
😁😄谢谢你的阅读。😼😸
相关文章:

【数据结构与算法】堆的实现(附源码)
目录 一.堆的概念及结构 二.接口实现 A.初始化 Heapinit 销毁 Heapdestroy B.插入 Heappush 向上调整 AdjustUp 1.Heappush 2.AdjustUp C.删除 Heappop 向下调整 AdjustDown D.堆的判空 Heapempty 堆顶数据 Heaptop 堆的大小 Heapsize 三.源码 Heap.h He…...

win10彻底永久关闭自动更新【亲测有效】
一、禁用Windows Update服务 1、同时按下键盘 Win R,打开运行对话框,然后输入命令 services.msc ,点击下方的“确定”打开服务,如下图所示。 2、找到 Windows Update 这一项,并双击打开,如图所示。 3、右击…...

【Unity UPR】造个获取深度法线纹理的轮子
描边需要深度法线纹理的加持,效果才能达到最好,但URP下很多版本不支持直接获取_CameraNormalsTexture,而我本人也尝试了一下在12.1.7下偷懒直接拿SSAO里的Depth Normal图, 虽然也能实现吧,但是需要打开SSAO的同时&…...
用 Python解析HTML页面
用 Python 解析 HTML 页面 在网络爬取的过程中,我们通常需要对所爬取的页面进行解析,从中提取我们需要的数据。网页的结构通常是由 HTML 标签所组成的,通过对这些标签的解析,可以得到网页中所包含的有用信息。在 Python 中&#…...
python logging 详解
python logging 详解1. 导入logging模块2. 配置日志记录器3. 记录日志消息4. 自定义日志记录器5. 日志轮换6. 日志过滤器7. 日志异常跟踪8. 日志输出到控制台和文件9. 使用配置文件10. 使用第三方库11. format格式详解12. 总结Python的logging模块提供了灵活的日志记录功能&…...

( “树” 之 DFS) 687. 最长同值路径 ——【Leetcode每日一题】
687. 最长同值路径 给定一个二叉树的 root ,返回 最长的路径的长度 ,这个路径中的 每个节点具有相同值 。 这条路径可以经过也可以不经过根节点。 两个节点之间的路径长度 由它们之间的边数表示。 示例 1: 输入:root [5,4,5,1,1,5] 输出&…...
Elasticsearch解决不能修改索引、字段问题解决方案
问题1: 由于es索引不能删除,不能修改,在不影响原数据的情况下,并且生产服务不停机的情况下,怎么修改索引,并保留原索引内的数据? 基于kibanna的dev Tools执行参数,淘汰postman&…...
面试官在线改简历 | 只有6秒!程序员简历这样写才能抓住科技公司大佬的眼球
其实每一份简历 每一个瑞库特 可能也就平均花6秒钟的时间看一看 来进行一个快速的筛选 一份好的简历到底应该长什么样 同时呢在我们写简历的过程当中 应该避免什么样子的错误和误区 那我们今天呢来聊聊这个简历的事 大家知道 每次到了招聘高分期啊这些大的公司 像谷歌Facebook…...

IM即时通讯-7-如何设计通知提醒
本文大纲 本文从为什么做通知提醒, 以及如何设计通知提醒, 以及如何衡量通知提醒三方面解释了如何设计通知提醒。 对于重点的如何设计通知提醒, 通过拆分前台和后台, 前台采用自建或者二方通道, 后台采用厂商信令通道…...

赛狐ERP | 亚马逊选品方法与策略详解:如何挑选最优质的产品?
亚马逊作为全球电商巨头,其产品种类之丰富也是无人能及。然而,在如此繁杂的商品体系下,如何选品成为了摆在商家面前的一道难题。本文将从亚马逊选品的目标、方法、策略三个方面进行详细介绍。 一、选品的目标 在进行选择之前,必…...

【GCU体验】基于PyTorch + GCU跑通ResNet50模型并测试GCU性能
一、环境 地址:启智社区:https://openi.pcl.ac.cn/ 二、计算卡介绍 云燧T20是基于邃思2.0芯片打造的面向数据中心的第二代人工智能训练加速卡,具有模型覆盖面广、性能强、软件生态开放等特点,可支持多种人工智能训练场景。同时具备灵活的可…...

【机器视觉------标定篇(二)】三点成圆算法(求相机旋转中心)
应用场景 机器视觉项目应用中,相机安装在机器人上,并且需要定位产品返回坐标偏差以及角度偏差。 与九点标定配合使用,实现精准角度补偿。 算法输入 不共线的三点坐标 A(X₁,Y₁) ,B(X₂,Y₂&…...
AUTOSAR E2E详细介绍
E2E概述 E2E(End-To-End)是AUTOSAR为功能安全ISO26262提出的一个安全模块。这里的端(End)并不是指ECU与ECU之间,而是指通信ECU上的SW-C与SW-C之间。 在车载网络中,信息交换通常是从一个ECU发送信号,另一个ECU接收信号。对E2E而言,通常是从源SW-C生成信号,经过RTE(R…...
Dream 主题使用手册 - 基础篇
Dream 主题基于 Halo 博客系统开发,本文将介绍本主题一些功能的使用,文档将持续更新。 一、安装 & 更新 1.1 安装包安装 & 更新 进入主题 Release 界面:https://github.com/nineya/halo-theme-dream/releases 下载主题压缩包 halo…...

WSL下的Kafka开发容器:Docker搭建、API、整合
背景介绍 Kafka是一个分布式流处理平台,可以处理大规模数据流并支持实时数据流的处理。 本文介绍了如何在WSL下使用Docker搭建Kafka容器,并使用Python的kafka-python库和FastAPI框架实现了一个简单的API。同时,还将该服务整合到一个整体的d…...
cv2(OpenCV)下载安装
cv2对应库是OpenCV,官网下载链接:https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv 最好下载对应python版本的,通过pip命令安装可能会出现版本过高或者过低的问题,导致import cv2没问题,但是内部函数无法调用。 …...

【剑指 offer】旋转数组的最小数字
✨个人主页:bit me👇 ✨当前专栏:算法训练营👇 旋 转 数 组 的 最 小 数 字核心考点:数组理解,二分查找,临界条件 描述: 有一个长度为 n 的非降序数组,比如[1,2,3,4,5]…...
GB 9706.1-2020 医用电气设备第1部分:基本安全和基本性能的通用要求-1
这是份什么文件 这是一份中华人民共和国国家标准,具体为GB9706.1—2020,标准适用于医用电气设备,并规定了医用电气设备基本安全和基本性能的通用要求。主要涵盖了医疗电器设备与患者接触的各种要求,包括电气安全、机械防护、防护辐…...

认识C++《共、枚、指1》
目录 前言: 1.共用体的基本知识 2.匿名共用体 3.枚举 3.1设置枚举值 3.2枚举的应用场景 3.3枚举变量的取值范围 4.地址和自由存储空间 5.指针的思想 6.指针的声明和初始化 前言: 指针内容比较多,还需要再出一篇。久等了!!我看了我的…...
vim 一键配置
PS:本文是为了以后为了方便,做备忘的,今天用的时候找了半天很麻烦。 vim编辑器一键配置 在非root用户下执行上面的语句即可,不要在root用户下直接安装! 安装的时候需要输入root用户的密码,请找您的服主要一…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...