数据结构-堆的实现和应用

数据结构-堆的实现和应用

目录

1.堆的概念

2.堆的构建

3.堆的实现

4.堆的功能实现

4.1堆的初始化

4.2堆的销毁

4.3堆的插入

4.3.1向上调整

4.4堆的删除

4.4.1向下调整法

​编辑4.5取堆顶

5. 向上调整法和向下调整法比较

 6.堆的应用

6.1TOP-K问题

6.2TOP-K思路

6.2.1用前n个数据来建堆

6.2.2剩下的N-K 

6.3示例


1.堆的概念

堆的底层是数组,所以堆也是一种特殊的数组。

堆分为大堆和小堆

  • 大堆:父节点不小于子节点
  • 小堆:父节点不大于子节点

2.堆的构建

已经提到堆是一种数组,那么要怎么实现呢。

先以小堆为例,已知父节点不小于子节点,使用数组,数组下标0是根节点,1和2是他的子节点,接着1的子节点是3和4,2的子节点是5和6,这样就可以实现一个堆了。

3.堆的实现

既然是数组,就要有指针,容量大小。

4.堆的功能实现

4.1堆的初始化

4.2堆的销毁

4.3堆的插入

一直到这一步,都是和栈是相同的,因为我们插入数据了,这时我们无法保证这是一个堆,所以此时要进行向上调整。

4.3.1向上调整

因为此时插入是数据再最下面,所以要和上面的进行比较调整。

4.4堆的删除

我们是删除堆的最后一个元素,要怎么删除呢,我们可以将最后一个元素和第一个元素进行交换,然后使堆向下调整即可。

        

4.4.1向下调整法

4.5取堆顶

5. 向上调整法和向下调整法比较

推导时间复杂度,由于用图来表示有些难度,这里直接用笔写出来

这是向下调整法的推导过程

向下调整建堆的时间复杂度如图

下面是向上调整建堆的时间复杂度推导

总结:向上调整算法建堆是优于向下调整建堆的。

 6.堆的应用

6.1TOP-K问题

这种问题通常是在较大的数据样本中取出其中的最值,这时就可以通过堆来完成。

通常这类问题样本较大,排序就不太可取,可以建堆来实现。

6.2TOP-K思路

6.2.1用前n个数据来建堆

求最大的前n个就建小堆

求最小的前n个就建大堆

6.2.2剩下的N-K 

用剩下的N-K个数据来和堆顶数据比较,不满足就替换堆顶元素

6.3示例

#define _CRT_SECURE_NO_WARNINGS 1 #include"Heap.h" #include<time.h> void test() { HP hp; HPInit(&hp); HPPush(&hp, 2); HPPush(&hp, 4); HPPush(&hp, 1); HPPush(&hp, 1); printf("%d", HPTop(&hp)); } void CreateNDate() { int n = 10000; srand(time(0)); const char* file = "data.txt"; FILE* fin = fopen(file, "w"); if (file == NULL) { perror("fopen fail"); return; } for (int i = 0; i < n; i++) { int x = (rand() + i) % 1000000; fprintf(fin, "%d\n", x); } fclose(fin); } void topk() { int k = 0; printf("输入k的值\n"); scanf("%d", &k); const char* file = "data.txt"; FILE* fout = fopen(file, "r"); int* arr = (int*)malloc(sizeof(int) * k); for (int i = 0; i < k; i++) { fscanf(fout, "%d", &arr[i]); } //建堆 for (int i = (k - 1 - 1) / 2; i >= 0; i--) { AdjustDown(arr, i, k); } int x = 0; while (fscanf(fout, "%d", &x) != EOF) { if (x > arr[0]) { arr[0] = x; AdjustDown(arr, 0, k); } } for (int i = 0; i < k; i++) { printf("%d ", arr[i]); } fclose(fout); } int main() { CreateNDate(); topk(); return 0; }

Read more

基于Java+SpringBoot+SSM闲置物品循环交易保障系统(源码+LW+调试文档+讲解等)/闲置物品交易系统/循环交易平台/物品循环利用系统/交易保障机制/闲置物品处理系统/循环交易保障

基于Java+SpringBoot+SSM闲置物品循环交易保障系统(源码+LW+调试文档+讲解等)/闲置物品交易系统/循环交易平台/物品循环利用系统/交易保障机制/闲置物品处理系统/循环交易保障

博主介绍 💗博主介绍:✌全栈领域优质创作者,专注于Java、小程序、Python技术领域和计算机毕业项目实战✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 2025-2026年最新1000个热门Java毕业设计选题大全✅ 2025-2026年最新500个热门微信小程序毕业设计选题大全✅ Java毕业设计最新1000套项目精品实战案例 微信小程序毕业设计最新500套项目精品案例 🌟文末获取源码+数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人 本文项目技术选型介绍 前端:Spring+SpringMVC+Mybatis 后端:SpringBoot+Mybatis 数据库:MySQL、SQLServer 开发工具:IDEA、Eclipse、Navicat等 ✌关于毕设项目技术实现问题讲解也可以给我留言咨询!!! 详细视频演示 请联系博主获取更详细的演示视频-源码编号4472 具体实现截图 框架介绍 前端技术介绍 SSM 框架在程序设计中具有不可替代的地位。它不仅提供了丰富的功能和强大的性能

By Ne0inhk
飞算JavaAI:Java开发新时代的破晓之光

飞算JavaAI:Java开发新时代的破晓之光

免责声明:此文章的所有内容皆是本人实验测评,并非广告推广,并非抄袭。如有侵权,请联系,谢谢! 【#飞算JavaAl炫技赛】 【#Java开发】 摘要:飞算JavaAI作为全球首款聚焦Java的智能开发助手,凭借自然语言交互、全流程智能生成等功能,实现开发效率十倍飞跃,生成规范高质量的完整工程代码,降低维护成本,适用于多行业,引领Java开发迈向智能化新时代。 一、引言:Java开发变革的序章 在数字化浪潮席卷的当下,Java作为软件开发领域的“中流砥柱”,地位举足轻重。从支撑互联网应用的稳定运行,到助力企业级系统的高效管理;从推动移动开发的蓬勃发展,到在大数据处理中发挥关键作用,Java凭借其强大的跨平台性、卓越的稳定性以及丰富的类库,成为无数关键业务运行的基石。据统计,全球Java开发者数量已突破千万,广泛分布于金融、电信、电商等各个行业,为数字世界的繁荣发展贡献着力量。 然而,随着业务需求的日益复杂和快速变化,传统Java开发模式正面临前所未有的挑战。开发周期漫长、效率低下、代码维护成本高昂等问题,如同沉重的枷锁,束缚着企业创新的步伐。相关数据显示,在企业级项目中,平均

By Ne0inhk
Java微服务架构设计模式:构建云原生时代的分布式系统

Java微服务架构设计模式:构建云原生时代的分布式系统

Java微服务架构设计模式:构建云原生时代的分布式系统 在云计算与微服务盛行的时代,分布式系统已成为企业级应用的核心架构。Java凭借其强大的生态系统和成熟的并发模型,在分布式系统开发中占据主导地位。本文将深入解析Java微服务架构的设计模式、实战经验与最佳实践。 一、微服务架构基础与演进 1.1 从单体架构到微服务 传统单体架构面临的主要挑战包括: * 技术栈僵化:难以采用新技术 * 可扩展性差:只能整体扩展,无法按需缩放 * 交付周期长:微小修改需要整体部署 * 可靠性低:单点故障导致整个系统崩溃 微服务架构通过将应用拆分为一组小型服务解决了这些问题,每个服务: * 围绕业务能力构建 * 可独立部署和扩展 * 拥有独立的数据存储 * 通过轻量级机制通信 单体应用网关服务用户服务订单服务产品服务用户数据库订单数据库产品数据库 图:从单体架构到微服务架构的演进 1.2 Java微服务生态体系 Java拥有最完善的微服务开发生态: 组件类型主流框架特点开发框架Spring Boot快速开发、自动配置服务治理Spring Cloud Netfl

By Ne0inhk
Java 内部类

Java 内部类

文章目录 * 内部类 * 实例内部类 * 静态内部类 * 匿名内部类 * 局部内部类 内部类 1. 一个事物的内部,还需要一个完整的结构进行描述,而这个结构只为外部服务,这个内部的完整结构叫内部类 2. 可以将一个类定义到另一个类内,或一个方法内,里面的是内部类,外面的是外部类 实例内部类 1. 如何实例化内部类 2. 外部类的成员在内部类中都能直接访问 packagetest2;class outClass{privateint a =3;publicstaticint b =2;class inClass{privateint a =1;// 在运行时确定的// static修饰的调用不需要实例化就能调用,而这个变量在内部类需要实例化内部类才能使用// public static int d = 2;publicstaticfinalint d =3;// 在编译的时候就确定了,是个常量,不依赖于实例化publicint

By Ne0inhk