调建堆的时间复杂度的计算与topK问题

建堆复杂度的计算

向下调整建堆

第一层有2^0个节点,最坏向下调整h-1次,第二层有2^1个节点,最坏向下调整h-2次,以此类推,将每一层所有节点最坏情况需要调整的次数相加,就能得到一个式子:

T(h) = 2^0 *(h-1) + 2^1 * (h-2) + 2^2 * (h-3) + ... + 2^{h-3} * 2 +2^{h-2}*1

最后到达(n-1)层,有2^{h-2}个节点,最坏需要向下调整1次.

而要求出该和式的计算,利用错位相减法,两边同乘2,再两式相减即可得

T(h) = 2^h - 1 - h

而我们又知道对于高度为h的满二叉树的节点个数与高度的关系

N=F(h) = 2^h -1

带入原式可得

对于N来说,对数的数量级可以忽略不计.

所以向下调整建堆时间复杂度是O(N).

向上调整建堆

同样写出堆的总调整数公式

2^1*1 +2^2*2 +2^3*3+... + 2^{h-2}*(h-2)+ 2^{n-1}*(h-1)

同样错位相减并带入节点数与树高度之间关系可得

对于nlogn来说,n的数量级可以忽略不计.

向上调整建堆时间复杂度是O(NlogN).

故在堆排序中只用向下调整建堆即可.

topk问题

在所有数据中找到最大(小)的k个数.

1.堆排序

将所有数据存储到堆里面,再进行堆排序即可,但如果要求低内存我们就可以分k次,每次找10个,再将k个查找的堆中找到的共10k个数据再进行堆排序即可。代码如下:

void TestHeap1()
{int a[] = { 4,2,8,1,5,6,9,7,3,2,23,55,232,66,222,33,7,1,66,3333,999, 15155 };HP hp;HPInit(&hp);for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]);}printf("\n");*///找出最大的前k个int k = 0;scanf("%d", &k);while (k--){printf("%d ", HPTop(&hp));HPPop(&hp);}printf("\n");HPDestroy(&hp);
}

2.建k个数的小堆

剩下的数与栈顶数据相比较,如果比栈顶数据大,就覆盖并且向下调整,这样,这个k个数的小堆就是我们所要的最大的那k个数.

先创建数据

void CreateNDate()
{// 造数据int n = 100000;srand(time(0));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (int i = 0; i < n; ++i){int x = (rand() + i) % 10000000;//保证其小于一千万fprintf(fin, "%d\n", x);//将数据导入data.txt中}fclose(fin);
}

创建一个数组

int* kminheap = (int*)malloc(sizeof(int) * k);
if (kminheap == NULL)
{perror("malloc fail!");return;
}

再打开数据文件并读取其中的前k个数

const char* file = "data.txt";
FILE* fout = fopen(file, "r");
if (fout == NULL)
{perror("fopen error");return;
}// 读取文件中前k个数
for (int i = 0; i < k; i++)
{fscanf(fout, "%d", &kminheap[i]);
}

再建立k个数的小堆,并读取剩下的N-k个数.

// 建K个数的小堆
for (int i = (k - 1 - 1) / 2; i >= 0; i--)//最后一个节点的下标减一再除以二得到最后一个非叶子节点
{AdjustDown(kminheap, k, i);
}// 读取剩下的N-K个数
int x = 0;
while (fscanf(fout, "%d", &x) > 0)//fscanf失败返回-1,所以这里我们让其大于0即可
{if (x > kminheap[0]){kminheap[0] = x;//将此数据与堆顶数据交换AdjustDown(kminheap, k, 0);}
}printf("最大前%d个数:", k);
for (int i = 0; i < k; i++)
{printf("%d ", kminheap[i]);//此时堆里数据就是最大的前k个
}
printf("\n");

整合起来

void TestHeap3()
{int k;printf("请输入k>:");scanf("%d", &k);int* kminheap = (int*)malloc(sizeof(int) * k);if (kminheap == NULL){perror("malloc fail");return;}const char* file = "data.txt";FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}// 读取文件中前k个数for (int i = 0; i < k; i++){fscanf(fout, "%d", &kminheap[i]);}// 建K个数的小堆for (int i = (k - 1 - 1) / 2; i >= 0; i--)//最后一个节点的下标减一再除以二得到最后一个非叶子节点{AdjustDown(kminheap, k, i);}// 读取剩下的N-K个数int x = 0;while (fscanf(fout, "%d", &x) > 0){if (x > kminheap[0]){kminheap[0] = x;AdjustDown(kminheap, k, 0);}}printf("最大前%d个数:", k);for (int i = k - 1; i >= 0; i--)//最后将数组数据倒序打印出来就可以达成数据由大到小的打印了
{printf("%d ", kminheap[i]);
}printf("\n");
}

这里我们创建了10万个数据,并且我主动将其中的几个数据加上几个0检测算法是正确的.

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

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

相关文章

FanySkill源文件修改,快捷键以及新增任务栏选项

FanySkill源文件修改&#xff0c;快捷键以及新增任务栏选项 一、文件下载二、快捷键设置三、任务栏四、本人配置 一、文件下载 自行去PCB联盟网下载&#xff0c;因为那边下载要联盟币&#xff0c;我不清楚我免费提供会不会给我带来没必要的损失&#xff0c;敬请谅解。 要下载的…

怎么为自己的VPS选择合适的CPU和RAM?

为网站选择VPS&#xff08;虚拟专用服务器&#xff09;与为家庭或办公室选择台式机或笔记本电脑没有什么不同。基本上&#xff0c;您要做的就是查看硬件配置并比较功能和价格。 然而&#xff0c;虽然您可能对个人计算机所需的资源类型有一个粗略的估计&#xff0c;但为服务器获…

jQuery 添加元素

jQuery 添加元素 jQuery 是一个广泛使用的 JavaScript 库&#xff0c;它简化了 HTML 文档的遍历、事件处理、动画和 Ajax 交互。在本文中&#xff0c;我们将探讨如何使用 jQuery 添加元素到 HTML 文档中。这对于动态更新用户界面&#xff0c;响应用户操作或从服务器获取数据非…

一文理清OCR的前世今生

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

EventBus之Reactor实战

如果你想要使用一个轻量级的消息中间件&#xff0c;不需要分布式支持&#xff0c;那么可以选择RxJava或者Reactor&#xff0c;本文将讲述如何入门使用该框架&#xff0c;以及常用的一些功能 生产者 广播多消费者模式 Sinks.Many: 创建一个允许我们将数据推送到一个Flux的sin…

队列(数据结构篇)

数据结构之队列 队列(queue) 概念&#xff1a; 队列也是一种线性表&#xff0c;使用队列时插入在一端进行而删除则在另一端进行&#xff0c;队列的基本操作是入队&#xff0c;它是在表的末端(也叫做队尾)插入一个元素&#xff0c;出队&#xff0c;它是删除在**表的开头(**队…

Springboot 项目启动时扫描所有枚举并存入缓存(redis)

为什么这么做? 为了springboot 注解属性转换字典方便一点(使用缓存的方式在Springboot 启动时获取字典数据) 在启动时会扫描com.vehicle.manager.core.enumerate包下的所有枚举(包括类中的内部枚举),并取出对应属性以json的方式存入redis 目录结构如下: RedisUtil可以在Red…

elasticsearch的入门与实践

Elasticsearch是一个基于Lucene构建的开源搜索引擎。它提供了一个分布式、多租户能力的全文搜索引擎&#xff0c;具有HTTP web接口和无模式的JSON文档。以下是Elasticsearch的入门与实践的基本步骤&#xff1a; 入门 安装Elasticsearch&#xff1a; 从Elasticsearch官网下载对…

DLT645电表数据 转IEC104项目案例

案例说明 设置网关采集DLT645电表数据数据把采集的数据转成IEC104协议转发给其他系统。 VFBOX网关工作原理 VFBOX网关是协议转换网关&#xff0c;是把一种协议转换成另外一种协议。网关可以采集西门子&#xff0c;欧姆龙&#xff0c;三菱&#xff0c;AB PLC&#xff0c;DLT64…

南开大学漏洞报送证书【文尾有福利】

证书介绍 获取来源&#xff1a;edusrc&#xff08;教育漏洞报告平台&#xff09; url&#xff1a;教育漏洞报告平台(EDUSRC) 兑换价格&#xff1a;30金币​ 获取条件&#xff1a;南开大学任意中危或以上级别漏洞 证书规格&#xff1a;证书做了木框装裱&#xff0c;显得很高…

【哈尔滨等保测评:金融行业安全的钢铁长城】

在当今高度信息化的社会中&#xff0c;网络安全已成为各行各业不可忽视的关键议题&#xff0c;尤其对于金融行业而言&#xff0c;信息安全更是至关重要的生命线。哈尔滨市作为东北地区的重要经济枢纽&#xff0c;其金融行业在享受数字化转型带来的便利与效率的同时&#xff0c;…

常量池你了解多少

第1部分&#xff1a;引言 JVM简介 Java虚拟机&#xff08;JVM&#xff09;是一个可以执行Java字节码的虚拟计算机。它是Java平台的核心组成部分&#xff0c;允许Java程序在不同的操作系统和硬件平台上运行。JVM不仅提供了内存管理、垃圾回收等基础服务&#xff0c;还支持多种…

我工作中用Redis的10种场景

Redis作为一种优秀的基于key/value的缓存&#xff0c;有非常不错的性能和稳定性&#xff0c;无论是在工作中&#xff0c;还是面试中&#xff0c;都经常会出现。 今天这篇文章就跟大家一起聊聊&#xff0c;我在实际工作中使用Redis的10种场景&#xff0c;希望对你会有所帮助。 …

逆向学习Windows篇:C++中多线程的使用和回调函数的实现

本节课在线学习视频&#xff08;网盘地址&#xff0c;保存后即可免费观看&#xff09;&#xff1a; ​​https://pan.quark.cn/s/385577c66515​​ 在Windows环境下&#xff0c;C是一种强大的编程语言&#xff0c;它不仅支持面向对象编程&#xff0c;还提供了对系统级编程的直…

竞赛选题 python opencv 深度学习 指纹识别算法实现

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python opencv 深度学习 指纹识别算法实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;4分创新点&#xff1a;4分 该项目较为新颖…

java干货 线程间通信

文章目录 一、线程间通信1.1 为什么要处理线程间通信&#xff1f;1.2 什么是等待唤醒机制&#xff1f; 二、等待唤醒机制使用2.1 等待唤醒机制用到的方法2.1.1 wait2.1.2 notify 2.2 线程通信代码实践2.2.1 重要说明2.2.2 代码 一、线程间通信 1.1 为什么要处理线程间通信&…

windows系统使用nvidia-smi命令办法

参考&#xff1a; https://blog.csdn.net/Castlehe/article/details/114978005 老版本的cuda&#xff0c;nvidia-sim.exe这个软件是位于&#xff1a;C:\Program Files\NVIDIA Corporation\NVSMI 新版本的cuda&#xff08;比如cuda11.0&#xff09;&#xff0c;nvidia-sim.exe这…

springBoot高校宿舍交电费系统-计算机毕业设计源码031552

摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作…

忘记 iPhone 密码:如果忘记密码,如何解锁 iPhone

为了提高个人数据的安全性&#xff0c;用户通常会为不同的帐户和设备创建不同的复杂密码。虽然较新的 iPhone 型号具有生物识别和面部解锁功能&#xff0c;但这些功能并不总是有效 - 如果您忘记了 iPhone 的密码&#xff0c;您可能会遇到麻烦。 iPhone 用户和 Android 用户一样…

MYSQL 四、mysql进阶 4(索引的数据结构)

一、为什么使用索引 以及 索引的优缺点 1.为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构&#xff0c;就好比一本教科书的目录部分&#xff0c;通过目录中找到对应文章的页码&#xff0c;便可快速定位到需要的文章。Mysql中也是一样的道理&#xff0c;进行数…