堆应用:Top-K问题

目录

一、介绍

二、思路

三、代码实现

1.创造数据

2、排序

代码讲解:

注:向下调整


一、介绍

TOP-K 问题:即求数据结合中前 K 个最大的元素或者最小的元素,一般情况下数据量都比较大
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。

二、思路

对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:
1. 用数据集合中前 K 个元素来建堆
前k个最大的元素,则建小堆
前k个最小的元素,则建大堆
2. 用剩余的 N-K 个元素依次与堆顶元素来比较,不满足则替换堆顶元素
将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素

三、代码实现

1.创造数据

当数据含量极大时,我们一般采用文件操作,去存储数据。


//创造数据

void CreatNDate()
{
	int n = 1000;

	srand((size_t)time(NULL));

	const char* file = "date.txt";

	FILE* fin = fopen(file, "w");	//文件指针
	if (fin == NULL)
	{
		perror("fopen fail");
		return;
	}

	for (int i = 0; i < n; i++)
	{
		int x = rand() % 100;

		fprintf(fin, "%d\n", x);		//对文件指针进行操作
	}

	fclose(fin);		//关闭文件指针
}

2、排序

代码讲解:

代码具体可以分为以下步骤:

1.打开文件,读取数据

2.利用K个数据建堆

3.依次比较,进行替换、调整

4.释放空间、关闭文件、文件指针置空。


//TOP-K :先读取    再: 1.建堆  2.替换
// 
// 
// 求大,建小堆;求小,建大堆

void PrintTopK(int k)
{
	const char* file = "date.txt";		//需要操作的文件名

	FILE* fout = fopen(file, "r");		//文件指针会伴随操作,不断移动

	if (fout == NULL)
	{
		perror("fopen fail");

		return;
	}


	//读取

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

	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &arr[i]);			//空格、“\n”会被默认为换行符
	}

	//建堆:传最后一个父亲的下标建堆

	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, k, i);
	}


	//遍历筛选

								//此时文件指针已经到了第6个数据
	while (!feof(fout))			//当没有到文件末尾时。
	{
		int x = 0;
		fscanf(fout, "%d", &x);
		if (arr[0] < x)
		{
			arr[0] = x;

			AdjustDown(arr, k, 0);		//parent下标是 0
		}
	}

	for (int i = 0; i < k; i++)
	{
		printf("%d ", arr[i]);
	}

	putchar(10);

	free(arr);
	arr = NULL;
}



	fclose(fout);
	fout = NULL;

注:向下调整

算法:向上/向下调整算法-CSDN博客

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值