TOPK问题的求解

本文介绍了如何在大量数据无法存储于内存时,通过构造文件和堆数据结构(小堆或大堆)来找出最大或最小的前K个数。首先创建包含100万个随机数的文件,然后读取并构建堆,接着逐个从文件读取数据并与堆顶比较,确保堆中的K个数始终是最大或最小。算法的时间和空间复杂度有详细分析。
摘要由CSDN通过智能技术生成

在这片文章详解二叉树-CSDN博客中我们提到,如果要在非常多的数据(内存存不下)中找到最大或最小的前K个数,我们需要先构建一个K个数的小堆或大堆;再跟堆顶数据比较

要找最大的前K个数建小堆;要找最小的前K个数建大堆

1.构造数据

既然数据在内存中存不下,我们就放到文件中;需要构造一个有很多数据的文件

  • 我们以“w”的方式打开一个文件,如果该文件不存在,则会先创建该文件
  • 假设文件需要100万个数据;使用rand函数随机取数,用fprintf写文件
//构造数据
void CreateData()
{
	srand(time(0));

	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
	{
		perror("CreateData:create data fail");
		exit(-1);
	}

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

	fclose(pf);
	pf = NULL;
}

2.建堆

我们就拿取最大的前K个数来示范了,取最小的前K个数只要将建小堆改成建大堆即可

  • 首先向文件读取k个数据,放到创建好的数组中
  • 利用向下调整算法,将这k个数建成小堆
	//建小堆
	int* minHeap = (int*)malloc(sizeof(int) * k);
	if (minHeap == NULL)
	{
		perror("PrintTOPK:malloc fail");
		exit(-1);
	}

	for (int i = 0; i < k; i++)
	{
		fscanf(pf, "%d", &minHeap[i]);
	}
	
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(minHeap, k, i);
	}

3.与堆顶数据比较

  • 利用fscanf的返回值来判断文件是否结束
  • 将读取到的数据与堆顶数据比较,如果比堆顶数据大,则交换,再对堆顶数据执行一次向下调整
	//堆顶数据与文件后面数据比较
	int x = 0;
	while (fscanf(pf, "%d", &x) != EOF)
	{
		if (x > minHeap[0])
		{
			minHeap[0] = x;
			AdjustDown(minHeap, k, 0);
		}
	}

4.复杂度计算

空间复杂度:O(K)

时间复杂度:O(N*\log_{2}{K} )


源码:TOPK/TOPK · baiyahua/LeetCode - 码云 - 开源中国 (gitee.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值