topk问题

前言

这道题要求我们在海量的数据里面找出最大的前k个,并且这些数据庞大到难以存储在内存中(本文选用的数据个数为1000000000),以至于只能在硬盘中,通过文件读写的形式放到内存中

一、难点?

无法全部存储

十亿个数据,若全都是整形,那么大约需要4G才能全部存储完,而且在文件中又没办法很好地排序

二、解决方法

在这里插入图片描述
最大的前K个建小堆(因为要把大的沉底)
比堆顶元素大的就替换,看似在堆顶的元素已经是最大的了,但实际上,比他大的还有k-1个在底下

最小的前k个建大堆(因为要把小的沉底)
想要什么类型的数就把什么类型的数沉底

三、代码演示及检验

(文件构建)

//造资源
void test2()
{
	srand(time(0));
	int n = 1000000000;
	const char* txt = "data.txt";
	FILE* fin = fopen(txt, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	for (int i = 0; i < n; i++)
	{
		int ran = rand() % 10000;
		fprintf(fin, "%d\n", ran);
	}
	//此处为了方便检验,放置了七个最大的数
	//默认topk中的k == 7
	fprintf(fin, "%d\n", 20000);
	fprintf(fin, "%d\n", 20001);
	fprintf(fin, "%d\n", 20002);
	fprintf(fin, "%d\n", 20003);
	fprintf(fin, "%d\n", 20004);
	fprintf(fin, "%d\n", 20005);
	fprintf(fin, "%d\n", 20006);
	
	fclose(fin);
	fin = NULL;
}

正文:

//向下调整
void DownAdjust(int* arr, int size, int parent)
{
	int child = parent * 2 + 1;

	while (child < size)
	{
		//找出两个孩子中最大的
		if (child + 1 < size && arr[child + 1] < arr[child])
		{
			child++;
		}

		if (arr[parent] > arr[child])
		{
			Swap(&arr[parent], &arr[child]);
			parent = child;
			child = child * 2 + 1;
		}
		else
		{
			break;
		}

	}
}

//向上调整
void UpAdjust(int* arr, int child)
{
	
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (arr[child] < arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}

	}
	
}

//交换两个数
void Swap(HPDataType* a, HPDataType* b)
{
	HPDataType tmp = *a;
	*a = *b;
	*b = tmp;
}


//topk问题
void test3()
{
	int k = 7;
	const char* txt = "data.txt";
	FILE* fin = fopen(txt, "r");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}
	
	int * arr = (int *)malloc(sizeof(int) * k);
	if (arr == NULL)
	{
		perror("malloc");
		return;
	}

	//建小堆
	for (int i = 0; i < k; i++)
	{
		fscanf(fin, "%d", arr + i);
		UpAdjust(arr, i);
	}

	int data = 0;
	for (int i = 0; i < 20; i++)
	{
		fscanf(fin, "%d", &data);
		if (data > arr[0])
		{
			Swap(&data, &arr[0]);
			DownAdjust(arr, 7, 0);
		}
	}

	
}

总结

以上就是今天要讲的内容,本篇文章着重讲解了topk问题的解题思路,在力扣以及牛客网中还会有很多类似的题目,今后将会持续更新,敬请关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值