堆的实现及其应用

堆的概念

        堆是完全二叉树,分为大堆和小堆。大堆:任何一个父亲都大于等于孩子,小堆:任何一个父亲都小于等于孩子。

堆的实现

目录

typedef int HPDataType;typedef struct Heap
{ HPDataType* a;int size;int capacity;
}HP;//交换函数
void Swap(HPDataType* p1, HPDataType* p2);
//堆的初始化和销毁
void HPInit(HP* php);
void HPDestroy(HP* php);
//堆的插入和删除
void HPPush(HP* php, HPDataType x);
void HPPop(HP* php);
//取堆数据和判空
HPDataType HPTop(HP* php);
bool HPEmpty(HP* php);
//向上调整和向下调整
void AdJustUp(HPDataType* a, int child);
void AdJustDown(HPDataType* a, int n, int parent);

1.堆的初始化

void HPInit(HP* php)
{assert(php);php->a = NULL;php->size = php->capacity = 0;
}

可以选择在堆的初始化过程直接对空间大小进行赋值,在这里选择不开空间。

2.堆的销毁

void HPDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;
}

3.交换函数

void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}

4.向上调整

        堆在数组中存储,所以根节点的小标为孩子节点下标减一再除以二,向上调整即将孩子节点向上调整,直到满足要求的大堆(小堆)建成。

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;}}
}

5.向下调整

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;}}}

6.堆的插入

void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a, newcapacity * sizeof(HPDataType));if (tmp == NULL){perror("realloc fail!");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdJustUp(php->a, php->size - 1);
}

我们选择在堆插入函数中进行空间的开创。

7.堆数据删除

        对于堆中数据的删除,删除叶子结点数据意义不大,我们主要是要删除顶层节点数据,思路将顶部数据进行调整到最后的叶子结点处,在对其进行删除即可。

void HPPop(HP* php)//向下调整算法,可用于topk问题(找最大(最小)的几个值)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdJustDown(php->a, php->size, 0);
}

8.取堆顶数据

        对于只有一条语句的函数,我们为了方便调控,仍进行函数调用。

HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}

9.堆的判空

bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

堆排序

建堆

        通过循环调用向上调整函数,可以将数组调整为堆。代码如下:

void HeapSort(int* a, int n)
{for (int i = 0; i < n; i++){AdJustUp(a, i);}
}

        另外,若使用向下调整建堆时间复杂度会更低

排序

升序建大堆

如果升序建小堆,将顶层最小数据取出后,导致后面数据顺序全部混乱,所以我们建大堆。

将最大的数往堆最后位置数据交换,再将其放入新数组的最后一位即可。代码如下:

void HeapSort(int* a, int n)
{for (int i = 0; i < n; i++){AdJustUp(a, i);}int end = n - 1;while (end > 0){	Swap(&a[0], &a[end]);AdJustDown(a, end, 0);--end;}
}	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 HeapSort(int* a, int n)
{for (int i = 0; i < n; i++){AdJustUp(a, i);}int end = n - 1;while (end > 0){	Swap(&a[0], &a[end]);AdJustDown(a, end, 0);--end;}
}	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;}}//向上调整同理
}

如果觉得我写得不错的话,请别忘了点赞收藏加评论!!

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

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

相关文章

C语言之操作符

目录 一、二进制 原码、反码、补码 二、移位操作符 位操作符 三、 逗号表达式 四、下标访问[]、函数调用() 五. 操作符的属性 整型提升 算术转换 六、总结 一、二进制 其实2进制、8进制、10进制、16进制是数值的不同表示形式而已。 其实10进制是生活中经常使用的&am…

类别朴素贝叶斯CategoricalNB和西瓜数据集

CategoricalNB 1 CategoricalNB原理以及用法2 数据集2.1 西瓜数据集2.2 LabelEncoder2.3 OrdinalEncoder 3 代码实现 1 CategoricalNB原理以及用法 &#xff08;1&#xff09;具体原理 具体原理可看&#xff1a;贝叶斯分类器原理 sklearn之CategoricalNB对条件概率的原理如下&…

粉丝经济时代:微信订阅号如何助力中小企业增长

在数字化浪潮席卷全球的今天&#xff0c;微信订阅号凭借其独特的优势&#xff0c;成为了中小企业数字化出海的重要工具。作为NetFarmer&#xff0c;我们致力于帮助企业充分利用这一平台&#xff0c;推动业务发展和市场拓展。今天将深入探讨微信订阅号的概念、用途、使用方法、适…

mac安装高版本git(更新git)

问题 问题&#xff1a;新下载的idea&#xff0c;此idea的版本较高&#xff0c;但是在工作发现这个版本的git存在一定漏洞会导致一些信息泄露问题。 1.安装Homebrew 对于Mac更新git&#xff0c;最简单的就是使用brew命令。所以我们首先下载homebrew。已下载的同学忽略直接下一…

【数据结构陈越版笔记】进阶实验1-3.1:两个有序序列的中位数

我这答案做的可能不对&#xff0c;如果不对&#xff0c;欢迎大家指出错误&#xff0c;思路大部分直接写在注释中了。 进阶实验1-3.1&#xff1a;两个有序序列的中位数 已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列 A 0 , A 1 , . . . , A n −…

ES升级--05--快照生成 和备份

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 备份ES数据1.关闭集群自动均衡2.执行同步刷新3.停止集群节点的Elasticsearch服务4.修改Elasticsearch配置文件&#xff0c;开启快照功能&#xff0c;配置仓库目录为…

微信群发机器人.使用指南.

0.简介 1.介绍 微信群发机器人是用来群发微信消息的工具,通过控制电脑的键盘和鼠标操作微信app来实现群发.支持的消息类型有:文字,图片,视频,文件,小程序,位置等. 群发机器人也可以将微信联系人中的信息保存到电脑csv表格中,以供分析. 因其是通过模拟用户操作鼠标键盘来实现群…

the histogram of cross-entropy loss values 交叉熵损失值的直方图以及cross-entropy loss交叉熵损失

交叉熵损失值的直方图在机器学习和深度学习中有几个重要的作用和用途&#xff1a; 评估模型性能: 直方图可以帮助评估模型在训练数据和测试数据上的性能。通过观察损失值的分布&#xff0c;可以了解模型在不同数据集上的表现情况。例如&#xff0c;损失值分布的形状和范围可以反…

C++中extern “C“的用法

目的 extern "C"是经常用到的东西&#xff0c;面试题目也经常出现&#xff0c;然则&#xff0c;实际用时&#xff0c;还是经常遗忘&#xff0c;因此&#xff0c;深入的了解一下&#xff0c;以增强记忆。 extern "C"指令非常有用&#xff0c;因为C和C的近亲…

Android MediaMetadataRetriever获取视频宽高,Java

Android MediaMetadataRetriever获取视频宽高&#xff0c;Java public static int[] getVideoSize(Context ctx, Uri uri) {MediaMetadataRetriever retriever new MediaMetadataRetriever();int[] size {-1, -1}; //宽&#xff0c;高try {retriever.setDataSource(ctx, uri)…

双向转发检测BFD(学习笔记)

定义 双向转发检测BFD&#xff08;Bidirectional Forwarding Detection&#xff09;是一种全网统一的检测机制&#xff0c;用于快速检测、监控网络中链路或者IP路由的转发连通状况 BFD检测机制 BFD的检测机制是两个系统建立BFD会话&#xff0c;并沿它们之间的路径周期性发送B…

Java 开发实例:Spring Boot+AOP+注解+Redis防重复提交(防抖)

文章目录 1. 环境准备2. 引入依赖3. 配置Redis4. 创建防重复提交注解5. 实现AOP切面6. 创建示例Controller7. 测试8. 进一步优化8.1 自定义异常处理8.2 提升Redis的健壮性 9. 总结 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨…

King Media 8.2 中文版安装

King Media-Viral Magazine News Video是一个用于架设社交网站的php脚本&#xff0c;能让您创建一个视频、新闻和图像的新颖社交网站。 功能 支持&#xff1a;从Url、Youtube、Vimeo、Vine、Instagram、Metacafe、DailyMotion上传和分享图片通过Facebook、谷歌、雅虎、Github和…

EC20通信模块升级失败 Quectel QDLoader 9008

这里写自定义目录标题 usb驱动下载固件和升级软件下载开始升级上述过程升级失败&#xff0c;出现Quectel QDLoader 9008寻找解决方案&#xff0c;事了QPS t不行&#xff0c;最终使用这个Quectel_Customer_FW_Download_Tool软件解决下载链接&#xff1a; 所有下载驱动、固件、软…

C++数据结构02 队列及其应用

目录 队列及其特点 利用数组模拟队列的基本操作 创建队列 空队条件 元素入队 元素出队 模拟超市收银问题 队列操作 初始化 入队操作 出队操作 取出队首元素 STL模板中队列的基本使用 训练&#xff1a;约瑟夫问题 参考程序 队列及其特点 队列是一种特殊的线性表&am…

Mac如何卸载掉系统自带的预装软件吗 Mac第三方软件无法卸载是为什么 macbook系统软件怎么删除?

在使用Mac电脑时&#xff0c;有时候我们会发现系统预装的一些应用并不常用或者不符合个人需求&#xff0c;想要将它们卸载掉。然而&#xff0c;对于系统自带的软件&#xff0c;卸载并不简单&#xff0c;需要谨慎对待以免影响系统稳定性和功能正常运行。 一、Mac可以卸载掉系统自…

Android安全开发之 Provider 组件安全

Android系统中的Content Provider组件是一种用于在不同应用之间共享数据的机制。它提供了一种安全、可控的方式&#xff0c;允许应用访问其他应用的数据。然而&#xff0c;如果Provider组件的安全措施没有得到妥善实现&#xff0c;则可能会导致严重的安全漏洞&#xff0c;例如数…

比利时海外媒体宣发,发稿促进媒体通稿发布新形势-大舍传媒

引言 随着全球化的推进&#xff0c;海外媒体的影响力也日益增强。在这一背景下&#xff0c;比利时海外媒体的宣发工作成为了媒体通稿发布的新形势。大舍传媒作为一家专注于宣传推广的公司&#xff0c;一直致力于与比利时博伊克邮报&#xff08;boicpost&#xff09;合作&#…

用数据说话,效果好上一万倍,不是空口说白话的“好很多”

作为一名大数据开发者&#xff0c;我深知数据的有很大的魔力&#xff08;我这句话就没用数据&#xff0c;听上去很无力&#xff09;。数据不仅仅是数字和图表&#xff0c;它还能赋予我们强大的说服力和权威感。让我给你详细讲讲数据如何让理论插上翅膀。 目录 数据的“靠谱”…

文字悬停效果

文字悬停效果 效果展示 CSS 知识点 CSS 变量使用回顾-webkit-text-stroke 属性的运用与回顾 页面整体结构实现 <ul><li style"--clr: #e6444f"><a href"#" class"text">First</a></li><li style"--cl…