堆的实现及其应用

堆的概念

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

堆的实现

目录

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,一经查实,立即删除!

相关文章

高考志愿填报秘籍:未来篇

选择适合自己的大学和专业&#xff0c;对广大考生来说至关重要。从某种程度上来说&#xff0c;决定了考生未来所从事的行业和发展前景。为了帮助广大考生更加科学、合理地填报志愿&#xff0c;选择适合自己的大学和专业&#xff0c;本公众号将推出如何用AI填报高考志愿专栏文章…

C语言之操作符

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

MPLS的配置

1、IP可达--- 使用路由协议全网可达 2、配置 MPLS ——LDP [r2]mpls lsr-id 2.2.2.2 必须先定义 mpls 的router-id&#xff0c;要为本地设备的真实ip地址&#xff0c;且邻居可达&#xff0c;因为该地址将用于建立 TCP 会话&#xff0c;建议使用环回地址 [r2]mpls 再开…

嵌入式微处理器重点学习(二)

影响cache命中率的因素 影响Cache命中率的因素主要包括以下几个方面&#xff1a; Cache大小&#xff1a;一般来说&#xff0c;Cache的大小越大&#xff0c;其能够存储的数据也就越多&#xff0c;因此可能缓存更多需要访问的数据&#xff0c;从而提高命中率。但是&#xff0c;增…

MySQL为什么需要事务回滚机制

在MySQL中事务回滚通过日志完成&#xff0c;所有事务进行的修改都会先记录到回滚日志中&#xff0c;然后再对数据库中的对应行进行写入。当事务被提交后就无法回滚了。 回滚日志的作用&#xff1a; 能够在发生错误或用户执行rollback时提供回滚的相关信息。 在整个系统发生崩溃…

Sklearn简介、安装教程、入门学习

当谈到sklearn&#xff08;scikit-learn&#xff09;教程时&#xff0c;以下是一个清晰、分点表示和归纳的概述&#xff0c;结合了参考文章中的相关信息&#xff1a; 1. Sklearn简介 定义&#xff1a;Scikit-learn&#xff08;sklearn&#xff09;是Python中用于机器学习的开…

类别朴素贝叶斯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;推动业务发展和市场拓展。今天将深入探讨微信订阅号的概念、用途、使用方法、适…

【驱动】使用fdisk、parted等命令制作SD启动卡

1、检查文件大小 计算烧写的文件系统大小 和 SD卡的大小,判断SD是否可以装下文件系统 1.1 计算文件系统大小 1)在终端中输入命令 $ du ./filesystem -b --max-depth=0 661447340 ./filesystem2)在脚本中计算 data_size=$(du ./filesystem -b --max-depth=0 | gre…

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 −…

JavaScript clearInterval 清除页面所有定时器

清除页面所有定时器&#xff1a; var time setInterval(() > {console.log("hello world") }, 10000); //清除 for(var i 1;i<time;i){clearInterval(i); }还可以用&#xff1a; 这种方法可以确保页面上所有的定时器都被有效地清除&#xff0c;以防止它们继…

Oracle 排查慢SQL

Oracle 排查慢SQL select * from v s q l a r e a w h e r e r o w n u m < 10 ; s e l e c t ∗ f r o m v sqlarea where rownum<10; select * from v sqlareawhererownum<10;select∗fromvsql where rownum<10; select * from dba_hist_sqltext where rownum<…

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

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

第一百零九节 Java面向对象设计 - Java抽象类和方法

Java面向对象设计 - Java抽象类和方法 Java可以定义一个类&#xff0c;其对象不能被创建。 它的目的只是表示一个想法&#xff0c;这是其他类的对象共有的。 这样的类称为抽象类。 语法 我们需要在类声明中使用 abstract 关键字来声明一个抽象类。 例如&#xff0c;下面的…

[240614] 微软推迟发布 Recall AI 功能 | YouTube 尝试在服务器端注入广告

目录 微软推迟发布 Recall AI 功能YouTube 尝试在服务器端注入广告 微软推迟发布 Recall AI 功能 微软表示&#xff0c;由于担心隐私风险&#xff0c;不会在下周推出 “Recall” 功能&#xff0c;这是一项跟踪计算机使用情况的 AI 功能 Recall 功能能跟踪网页浏览&#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的近亲…

mysql安装配置教程(Linux+Windows)

mysql安装配置教程&#xff08;LinuxWindows&#xff09; 文章目录 mysql安装配置教程&#xff08;LinuxWindows&#xff09;摘要在 Linux 上安装和配置 MySQL1. 安装 MySQLUbuntu/DebianCentOS/RHEL 2. 配置 MySQL初始化 MySQL登录 MySQL创建数据库和用户配置 MySQL 文件 3. 测…