【C语言】Top K问题【建小堆】
池央 2024-08-11 09:35:01 阅读 94
前言
TopK问题:从n个数中,找出最大(或最小)的前k个数。
在我们生活中,经常会遇到TopK问题
比如外卖的必吃榜;成单的前K名;各种数据的最值筛选
问题分析
显然想开出40G的空间是不现实的,那应该怎么办呢?
答案是:建小堆
代码实现
<code>#include<stdio.h>
#include<stdlib.h>
#include<time.h>
// 造数据
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 (int i = 0; i < n; ++i)
{
int x = (rand() + i) % 1000000;
fprintf(fin, "%d\n", x);
}
fclose(fin);
}
void Swap(int* px, int* py)
{
int tmp = *px;
*px = *py;
*py = 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[child] < a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void PrintTopK(int k)
{
FILE* fout = fopen("data.txt", "r");
if (fout == NULL)
{
perror("fopen mail");
return;
}
int* minheap = (int*)malloc(sizeof(int) * k);
if (minheap == NULL)
{
perror("minheap mail");
return;
}
for (int i = 0; i < k; i++)
{
fscanf_s(fout, "%d", &minheap[i]);
}
//建小堆
for (int i = (k - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(minheap, k, i);
}
int x = 0;
int val = 0;
while (val = fscanf_s(fout, "%d", &x) != EOF)
{
if (x > minheap[0])
{
minheap[0] = x;
AdjustDown(minheap, k, 0);
}
}
for (int i = 0; i < k; i++)
{
printf("%d ", minheap[i]);
}
fclose(fout);
}
int main()
{
//CreateNDate();
printf("请输入k:>");
int k = 0;
scanf_s("%d", &k);
PrintTopK(k);
return 0;
}
运行结果:
结果验证
那我们怎么确定输出在屏幕上的数据就是最大的数据呢?
我们可以在已经创建的数据上面修改,如图后面111的是在原有数据上手动添加的
重新运行,结果与预期一致
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。