【数据结构与算法】堆的实现(附源码)
目录
一.堆的概念及结构
二.接口实现
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用户的密码,请找您的服主要一…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...