目录
一、什么是TOP-K问题
二、解决思路
一般的正常思路:
把这N个数建成大堆,Pop弹出K次堆顶,即可找出最大的前K个数,但是有些场景这种思路解决不了,例如N非常大时,假设N是10亿,10亿个数建堆所需的空间我们来计算一下:
4G感觉不多的话,如果一百亿数据呢?一千亿呢?
最优的解决思路:
三、文件流中实践TOP-K方法
我们来在文件中实践一下这个方法:
创建包含足够多整数的文件:
void CreateNData()
{
int n = 100000;
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() % 10000000;
fprintf(fin, "%d\n", x);
}
fclose(fin);
}
- 定义一个变量n,表示要生成的随机整数的数量为十万个。
- 使用srand函数设置随机数种子,time(0)返回当前时间的秒数,确保每次运行程序生成的随机数序列都不同。
- 定义一个文件名file,表示要生成的文件名。
- 使用fopen函数打开文件,以写入模式打开,如果没有文件,则创建一个,如果文件打开失败,输出一个错误信息并返回。
- 使用for循环生成n个随机整数,并使用fprintf函数将它们写入文件中。
- 使用fclose函数关闭文件。
找出最大的K个数
void PrintTopK(int k)
{
const char* file = "data.txt";
FILE* fout = fopen(file, "r");
if (fout == NULL)
{
perror("fopen error");
return;
}
int* kminheap = (int*)malloc(sizeof(int) * k);
if (kminheap == NULL)
{
perror("malloc error");
return;
}
for (int i = 0; i < k; i++)
{
fscanf(fout, "%d", &kminheap[i]);
}
for (int i = (k - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(kminheap, k, i);
}
int val = 0;
while (!feof(fout))
{
fscanf(fout, "%d", &val);
if (val > kminheap[0])
{
kminheap[0] = val;
AdjustDown(kminheap, k, 0);
}
}
for (int i = 0; i < k; i++)
{
printf("%d ", kminheap[i]);
}
printf("\n");
}
完整版代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void Swap(HPDataType* p1, HPDataType* p2)
{
HPDataType tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void AdjustDown(HPDataType* a, int size, int parent)
{
int child = parent * 2 + 1;
while (child < size) {
if (child + 1 < size && 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 CreateNData()
{
int n = 100000;
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() % 10000000;
fprintf(fin, "%d\n", x);
}
fclose(fin);
}
void PrintTopK(int k)
{
const char* file = "data.txt";
FILE* fout = fopen(file, "r");
if (fout == NULL)
{
perror("fopen error");
return;
}
int* kminheap = (int*)malloc(sizeof(int) * k);
if (kminheap == NULL)
{
perror("malloc error");
return;
}
for (int i = 0; i < k; i++)
{
fscanf(fout, "%d", &kminheap[i]);
}
// 建小堆
for (int i = (k - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(kminheap, k, i);
}
int val = 0;
while (!feof(fout))
{
fscanf(fout, "%d", &val);
if (val > kminheap[0])
{
kminheap[0] = val;
AdjustDown(kminheap, k, 0);
}
}
for (int i = 0; i < k; i++)
{
printf("%d ", kminheap[i]);
}
printf("\n");
fclose(fout);
}
int main()
{
CreateNData();
PrintTopK(5);
return 0;
}