文件中找TopK问题

news2024/9/20 12:33:25

目录

  • 1.解题思路
  • 2.创建一个文件并在文件中写入数据
  • 3.为什么要建立小堆而不建立大堆?
  • 4.如何在现有的数据中建立适合的大堆?
  • 5.代码实现

1.解题思路

TopK问题即是在众多数据中找出前K大的值,则可以根据堆的性质来实现,但在使用堆之前,我们要想办法先去建立一个堆,那么建立大堆还是小堆?答案是建立小堆.

2.创建一个文件并在文件中写入数据


void CreateNDate()
{
	// 造数据
	int n = 10000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	for (size_t i = 0; i < n; ++i)
	{
		int x = rand() % 1000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}

3.为什么要建立小堆而不建立大堆?

假设数据的范围是1到100,如果要求找出前10大的值,如果我们建立大堆,假设第一个值正好是最大的,那么这个堆里就不会在进入其他的值了,这明显是错误的.
在这里插入图片描述

但如果建立小堆,每个元素在插入的时候与堆首元素进行比较,如果比首元素大那就替换并向下调整,这样一来,就可以实现我们想要的结果.

4.如何在现有的数据中建立适合的大堆?

我们可以根据K的不同,建立不同大小的堆,加入要找前K个值,那么我们就建立大小为K的小堆,建堆又有两种方式,即向上调整法和向下调整法,在之前的文章中我证明了向上调整法的时间复杂度是O(N*logN)而向下调整法的时间复杂度是O(N),因此如果追求时间复杂的的话,向下调整法会更好


for (int i = (k-2)/2; i < k; i++)
{
	AdjustDown(topK, k, i);

}
/*for (int i = k - 1; i > 0; i--)
{
	AdjustUp(topK, i);
}*/

5.代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
	
}
void AdjustDown(int* 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[parent] > a[child])
		{
			Swap(&a[parent], &a[child]);
		}
		parent = child;
		child = parent * 2 + 1;
	}

}
void AdjustUp(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[parent] > a[child])
		{
			Swap(&a[parent], &a[child]);
		}
		child = parent;
		parent = (child - 1) / 2;

	}


}

void CreateNDate()
{
	// 造数据
	int n = 10000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	for (size_t i = 0; i < n; ++i)
	{
		int x = rand() % 1000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}
void PrintTopK(const char* file,int k)
{
	int* topK = (int*)malloc(sizeof(int) * k);
	assert(topK);
	FILE* fout = fopen(file, "r");//读取文件 file
	if (fout == NULL) {
		perror("open fail");
		return;
	}
	for (int i = 0; i < k; i++) {
		fscanf(fout, "%d", &topK[i]);
	}
	for (int i = (k-2)/2; i < k; i++)
	{
		AdjustDown(topK, k, i);

	}
	/*for (int i = k - 1; i > 0; i--)
	{
		AdjustUp(topK, i);
	}*/
	int val = 0;
	int ret= fscanf(fout, "%d", &val);
	while (ret != EOF)
	{
		if (val > topK[0])
		{
			topK[0] = val;
			AdjustDown(topK, k, 0);
		}
		ret = fscanf(fout, "%d", &val);
	}
	for (int i = 0; i < k; i++)
	{
		printf("%d ", topK[i]);


	}
	fclose(fout);


}
int main()
{
	CreateNDate();
	PrintTopK("data.txt", 10);
	return 0;


}



实际上,我们可以看出,虽然建堆的时间复杂度可以优化,但是后面的从文件中读取数据并进行判断是否替换的过程是无法进行优化的时间复杂度为O(N*logN),因此建堆的时间复杂度并不影响整个算法的时间复杂度

结尾:今天的分享到此结束,喜欢的朋友如果感觉有帮助可以点赞三连支持,咱们共同进步!

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

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

相关文章

敌手觊觎,核心研发项目源代码安全不可忽视!立即了解迅软DSE防泄密良策!

源代码作为企业的知识产权之一&#xff0c;也是企业的重要商业秘密&#xff0c;如果不慎被泄露可能会被竞争对手利用&#xff0c;对企业的业务和安全带来威胁以及不必要的法律风险。面对层出不穷的泄密事件&#xff0c;相关人员更应该提高对源代码的保护意识&#xff0c;加强企…

K歌利器-无线K歌麦克风模组-投影K歌解决方案

麦克风K歌模组是一种用于改善音频质量的麦克风系统&#xff1b;其发展可以追溯到20世纪50年代&#xff0c;如今&#xff0c;麦克风模组的技术发展已经非常成熟&#xff0c;可以提供更为优质的音频质量&#xff1b;支持多种不同的连接方式&#xff1b;可以在不同的设备上使用。 …

a-select:下拉组件实现筛选+远程搜索功能——基础积累

a-select:下拉组件实现筛选远程搜索功能——基础积累 效果图下拉筛选数据&#xff1a;远程搜索功能&#xff1a; 效果图 下拉筛选数据&#xff1a; <a-selectshow-searchv-model"form.jobPositionCode"placeholder"请选择岗位"style"width: 100%&q…

『Jmeter超级干货』| Linux下Jmeter安装配置、脚本设计执行、监控及报告完整过程

『Jmeter超级干货』| Linux下Jmeter安装配置、脚本设计执行、监控及报告完整过程 1 JDK安装部署1.1 JDK下载1.2 JDK配置 2 Jmeter安装部署2.1 Jmeter下载2.2 Jmeter安装2.3 Jmeter相关目录配置2.4 Jmeter启动配置2.5 检查并启动 3 Jmeter汉化3.1 临时修改3.2 永久修改 4 准备测…

Modbus TCP工业RFID读写器的选型要点

Modbus TCP工业RFID读写器是一种采用Modbus TCP通信协议的RFID读写器。它可以通过TCP/IP网络与计算机或其它设备进行通信&#xff0c;实现远程读取和写入RFID标签数据的目的。 与传统的RFID读写器相比&#xff0c;Modbus TCP工业RFID读写器具有更远的读写距离、更高的读写灵敏度…

CAD精品Eyeshot Fem 2023.3.630 -2023-11-05 Crack

2023.3.630 更新25天前 分享 跟随还没有人关注 改进的 Brep.TransformBy() 方法修复了工具栏内存泄漏修复了 glTF 材质导出期间的异常改进了 glTF 材质金属粗糙度设置修复了渐进式绘图和剪辑平面的错误在 Workspace.UseShaders 属性设置器中添加了缺少的 RenderContext.MakeCur…

Python 计算图像差分的三种方式(cv2,torchvision,numpy)

前言&#xff1a;最近在可视化图像残差时&#xff0c;发现几种不同的差分方法&#xff0c;下面分别给出每种差分方法的实现方式&#xff0c;并比较不同方法之间的差异。 目录 1️⃣ cv22️⃣ PIL & torchvision3️⃣ PIL & numpy 目标&#xff1a;对于给定的下述两张图…

Windows系列:Windows server 2016 部署路由与远程访问服务

Windows server 2016 部署路由与远程访问服务 前言环境要求服务器配置ip 设置"远程访问" 服务安装 "远程访问" 服务配置 ”远程访问“ 服务新建用户 客户机配置添加VPNping 前言 千万不要安装图上的几个服务&#xff0c;如果安装了&#xff0c;鼠标会失灵…

10.0 输入输出 I/O

IO操作主要是指使用Java程序完成输入&#xff08;Input&#xff09;、输出&#xff08;Output&#xff09;操作。所谓输入是指将文件内容以数据流的形式读取到内存中&#xff0c;输出是指通过Java程序将内存中的数据写入到文件中&#xff0c;输入、输出操作在实际开发中应用较为…

键盘打字盲打练习系列之指法练习——2

一.欢迎来到我的酒馆 盲打&#xff0c;指法练习&#xff01; 目录 一.欢迎来到我的酒馆二.指法练习 二.指法练习 前面一个章节简单地介绍了基准键位、字母键位和数字符号键位指法&#xff0c;在这个章节详细介绍指法。有了前面的章节的基础练习&#xff0c;相信大家对盲打也有了…

构建智能预约体验:深度解析预约系统源码的代码精髓

随着数字化时代的发展&#xff0c;预约系统在各行业中扮演着越来越重要的角色。本文将深入研究预约系统源码&#xff0c;通过代码示例分析其技术要点&#xff0c;为开发者提供实用的指导&#xff0c;助力构建智能、高效的预约体验。 技术栈综述 预约系统源码采用了现代化的技…

【JUC】十八、happens-before先行发生原则

文章目录 1、先行发生原则happens-before2、happens-before总原则3、8条happens-before规则4、案例 1、先行发生原则happens-before 在Java中&#xff0c;Happends-Before本质上是规定了一种可见性&#xff0c; A Happends-Before B&#xff0c;则A发生过的事情对B来说是可见的…

大模型fine-tune 微调

大模型的 Fine-tune 我们对技术的理解&#xff0c;要比技术本身更加重要。 正如我在《大模型时代的应用创新范式》一文中所说&#xff0c;大模型会成为AI时代的一项基础设施。 作为像水、电一样的基础设施&#xff0c;预训练大模型这样的艰巨任务&#xff0c;只会有少数技术…

滚珠丝杆在各种自动化设备中的作用

滚珠丝杆因其具有高精度、高刚度和长寿命等特性&#xff0c;成为许多设备中的重要组成部分&#xff0c;在许多行业中都有广泛的应用&#xff0c;接下来我们看看滚珠丝杆的具体应用有哪些&#xff1f; 1、打孔机&#xff1a;提供精确的导向&#xff0c;使打孔机的滑块能够沿固定…

数据库管理-第119期 记一次迁移和性能优化(202301130)

数据库管理-第119期 记一次迁移和性能优化&#xff08;202301130&#xff09; 1 迁移 之前因为DV组件没有迁移成功的那个PDB&#xff0c;后来想着在目标端安装DV组件迁移&#xff0c;结果目标端装不上&#xff0c;而且开了SR也没看出个所以然来。只能换一个方向&#xff0c;尝…

优化-查询数据接口太慢

有一个查询接口&#xff0c;主业务表有几万多条数据&#xff0c;没超过十万&#xff0c;由于没有使用分页&#xff0c;所以每次查询都要返回大几万的数据&#xff0c;然后问题是前端页面查询数据显示数据要转很久。 压缩响应体大小 我发现查询的时间是1秒多&#xff0c;但是浏…

Android中在google Map 上绘制历史路径

很多的App都会有这种需求&#xff0c;需要把自己的轨迹绘制在地图上来加标一段行踪&#xff0c;使得自己的行程展现出来&#xff0c;通过地图的展示&#xff0c;自己的行程也就一目了然了。 这里利用Google Map 把自己的行程展现出来&#xff0c;注意这里用到了上一章的基础&a…

关于最近Facebook的未经用户同意收集使用个人信息,

最近收到深圳市通信管理局的违法违规APP处置通知大概如下: 并且详细列举了 facebook sdk 在未经用户允许前调用的 TelephonyManager.getNetworkOperatorName(); 方法,获取运营商名称. 解决方法, 首先 在用户没有点击允许隐私条款前 不要调用任何Facebook sdk 方法,比如: Fac…

量子力学:探索微观世界的奇妙之旅

量子力学&#xff1a;探索微观世界的奇妙之旅 引言 在21世纪初&#xff0c;我们逐渐进入了一个以信息技术为主导的新时代。在这个时代&#xff0c;量子力学作为一门研究物质世界微观结构、粒子间相互作用以及能量与信息转换的基础科学&#xff0c;对我们的生活产生了深远的影响…

【Linux】:信号(一)产生

信号 一.前台进程和后台进程1.前台进程2。后台进程3.总结 二.自定义信号动作接口三.信号的产生1.键盘组合键2.kill信号进程pid3.系统调用1.kill函数2.raise函数3.abort函数 四.异常五.软件条件六.core文件 一.前台进程和后台进程 1.前台进程 一个简单的代码演示 像这种程序在…