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

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

目录

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

【STL库】哈希表的原理 | 哈希表模拟实现

【STL库】哈希表的原理 | 哈希表模拟实现

🫧 励志不掉头发的内向程序员:个人主页  ✨️ 个人专栏: 《C++语言》《Linux学习》 🌅偶尔悲伤,偶尔被幸福所完善 👓️博主简介: 文章目录 * 前言 * 一、哈希概念 * 二、直接定址法 * 三、哈希冲突 * 四、负载因子 * 五、将关键词转为整数 * 六、哈希函数 * 6.1、除法散列法/除留余数法 * 6.2、乘法散列法 * 6.3、全域散列法 * 七、处理哈希冲突 * 7.1、开放定址法 * (1)线性探测 * (2)二次探测 * (3)双重散列(了解即可) * 7.2、开放定址法代码实现 * (1)开放定址法的哈希表结构

By Ne0inhk
Bellman - Ford 算法与 SPFA 算法求解最短路径问题 ——从零开始的图论讲解(4)

Bellman - Ford 算法与 SPFA 算法求解最短路径问题 ——从零开始的图论讲解(4)

目录 前言 为什么Dijkstra算法面对负权值图会有误差??? 举例说明 什么是Bellman -Ford算法? BF算法的核心思想  什么是松弛  为什么最多松弛N-1次? 代码实现 举例  初始状态(dist[] 数组)  第 1 轮松弛(遍历所有边) 第 2 轮松弛 第 3 轮松弛 第 4 轮松弛(最后一次) 第 5 轮检测是否还能松弛(负环判断) 完整代码  BF算法的缺陷 SPFA算法 SPFA算法改进的地方 SPFA算法的原理 完整代码 结尾 前言 这是笔者图论系列的第四篇博客了,非常感谢大家的支持,因为本系列的数据很好看,笔者有了更多动力去更新 . 前三篇URL如下: 1. 图的概念,图的存储,图的遍历与图的拓扑排序——从零开始的图论讲解(

By Ne0inhk
当AI变成“需求读心术大师“:Python开发者如何用“脑洞算法“破解预测困局?

当AI变成“需求读心术大师“:Python开发者如何用“脑洞算法“破解预测困局?

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎点赞 + 收藏 + 关注哦 💕 当AI变成"需求读心术大师":Python开发者如何用"脑洞算法"破解预测困局? 📚 本文简介 本文探讨了AI需求预测的局限性及其与人类心理洞察的本质差异。通过Python代码示例(GradientBoostingClassifier模型)揭示了AI"读心术"实为基于历史数据的概率猜测,并运用mermaid图对比展示AI在情感理解、文化背景考量等方面的不足。关键发现: AI预测依赖表面行为数据,而人类能理解深层动机 开发者应结合算法与人文洞察,如文中小陈从"更快的马"解读出"便捷交通工具"的真实需求 提出Python开发场景对照表,显示人类在用户体验设计、错误处理等方面的温度优势 结论:AI预测是工具而非真理,开发者需保持批判思维,

By Ne0inhk