【数据结构】TOP-K问题/使用堆解决

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤

📃个人主页 :阿然成长日记 👈点击可跳转

📆 个人专栏: 🔹数据结构与算法🔹C语言进阶

🚩 不能则学,不知则问,耻于问人,决无长进

🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

文章目录

TOP-K问题

一、题目描述

假设有一亿个数据,内存存储不下,而我们只需要这一亿个数据中最大的前K个。

二、 思路:

1.:存前K个数据入堆

从第二个开始,每存储一个数据进来,就对其进行向上调整,使其一直保持为小堆。直到k-1个节点停止存储。

2.再从第K+1个数据开始读取

此时读取的数据就不再往堆中插入了,而是与堆顶元素进行比较,如果比堆顶大,那么就替换堆顶元素,然后进行基于小堆的向下调整。

3.所有数据读取完毕,堆中剩余的K个就是最大的K个数据

三、代码实现

1.随机产生一万个数据,存入文件中。

c 复制代码
void CreateNDate()
{
	// 造数据
	int n = 10000000;
	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) % 10000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}

2.找前K个最大值

c 复制代码
void PrintTopK(const char* filename, int k)
{
 建堆/用a中前k个元素建堆
	FILE* fout = fopen(filename, "r");
	if (fout == NULL)
	{
		perror("fopen fail");
		return;
	}
开辟K个元素空间
	int* minheap = (int*)malloc(sizeof(int) * k);
	if (minheap == NULL)
	{
		perror("malloc fail");
		return;
	}
将前k个元素读入数组minheap
	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &minheap[i]);
	}
 用前k个数建小堆,使用从下到上的向下调整方法建堆。
k-1下标的双亲节点是(k-1-1)/2;
	for (int i = (k - 2) / 2; i >= 0; --i)
	{
		AdjustDown(minheap, k, i);
	}


将剩余n-k个元素依次与堆顶元素交换,不满足,则替换
	int x = 0;
	while (fscanf(fout, "%d", &x) != EOF)
	{
		if (x > minheap[0])
		{
替换堆顶元素进堆
			minheap[0] = x;
并且进行调整
			AdjustDown(minheap, k, 0);
		}
	}

遍历完所有n个数据后,打印出堆中的数据,就是最大的K个数据啦!
	for (int i = 0; i < k; i++)
	{
		printf("%d ", minheap[i]);
	}
	printf("\n");

	fclose(fout);
}

// fprintf  fscanf

3.测试类:

c 复制代码
int main()
{
	//CreateNDate();
	PrintTopK("data.txt", 5);

	return 0;
}

四、时间复杂度和空间复杂度分析

🔸时间复杂度:O(N*logK);
N:节点个数。K:最大的前K个个数
如果N>>K,那么可以认为时间复杂度是O(N);这也是此算法的厉害之处。

🔸空间复杂度:O(K);
K:最大的前K个个数.

相关推荐
wabs6664 小时前
关于图论【卡码网117.软件构建的思考】
数据结构·算法·软件构建·图论·卡码网
mifengxing5 小时前
LeetCode 41.缺失的第一个正数|Hard题O(n)+O(1)最优解法深度解析
java·算法·leetcode·排序算法
Tongzhi20266 小时前
从部署到运维:通芝科技无感考勤一体机的全流程效率解析
运维·数据结构·科技·算法·贪心算法
Wang's Blog6 小时前
AI Agent白手起家30: 动态示例选择器之根据长度选择 Few Shot 示例
算法
oyguyteggytrrwwwrt7 小时前
自制交叉线路识别算法
算法
手写码匠7 小时前
华为云Flexus+DeepSeek征文|Dify 多智能体协同编排实战:R1 规划 + V3 执行,构建企业 Agent 团队
人工智能·深度学习·算法·aigc
晓天衡宇•评测社区8 小时前
FSR-Bench 前沿科学推理榜单发布:GPT-5.5 居首,“会推理”未必“能答对”
算法
程序喵大人10 小时前
【C++进阶】STL算法与函数对象 - 02 sort为什么需要随机访问迭代器
开发语言·c++·算法
hanlin0310 小时前
动态规划专练:力扣第121、122题
笔记·算法·leetcode
To_OC10 小时前
LC 74 搜索二维矩阵:换皮的二分查找,我居然一开始没看出来
javascript·算法·leetcode