一亿数据找Top K,内存仅存k个元素(Top—K问题)

问题导入:

假使有一亿个整数要去排序,从中找出k个最大值和k个最小值,当前的内存仅仅可以保留k个整数应当如何存储

内容扩展:

1GB=1024MB=1024*1024KB=1024*1024*1024Byte≈10.7亿字节

一个整形需要用到4个字节,一亿个整形要用到四亿个字节,大约是0.3725GB

核心思路:

数据不可以也不被允许放在内存里,大多数应该存储在磁盘文件中,内存中仅仅只存储维护一个大小为k的堆中,求最大的K个数据用小根堆,求最小的K个数据用大根堆

将文件data.txt放在磁盘中,程序采用fscanf或read一个一个读取数据,内存中仅仅保留k个候选元素,构成一个堆

时间复杂度:O(nlogk)[n是要处理的总数据量] 空间复杂度:O(k)

求最大K个元素,为何要去建立小根堆?

step1:先读取K个元素,建立小根堆

step2:小根堆的堆顶是这K个元素中最小的

step3: 继续遍历剩下n-k个元素:

  • 如果新元素x>堆顶元素,说明x比这K个元素里的最小值大
  • 将堆顶元素删去,换成x
  • 而后进行下沉调整,保持小根堆

同理求取最小的K个元素,建立大根堆

代码实践

文件data.txt写入

void CreatFile(void) { FILE* fput = fopen("data.txt", "w");//以写入的方式创建文件 if (fput == NULL) { perror("fopen"); return; } // 生成 100000 个 [0, 999999] 的整数 for (int i = 0; i < 100000; i++) { int a = (int)((double)rand() / ((double)RAND_MAX + 1) * 1000000);//rand()函数的返回值是一个伪随机整数,范围在0~RAND_MAX,除以RAND_MAX+1得到[0,1)的浮点数,再乘以1000000,并且强制转换为整数 fprintf(fput, "%d\n", a);//写入文件 } fclose(fput);//关闭文件 }

建立小根堆

// 交换两个整数 void swap(int* a, int* b) { int t = *a; *a = *b; *b = t; } // 小根堆向下调整 // arr: 堆数组, n: 堆大小, i: 当前要调整的节点下标 void AdjustDown(int* arr, int n, int i) { while (1) { int l = 2 * i + 1; int r = 2 * i + 2; int smallest = i; if (l < n && a[l] < a[smallest]) smallest = l; if (r < n && a[r] < a[smallest]) smallest = r; if (smallest == i) break; swap(&a[i], &a[smallest]); i = smallest; } } // 建小根堆 void BuildMinHeap(int a[], int n) { for (int i = (n - 2) / 2; i >= 0; --i) { AdjustDown(a, n, i); } }

求最大的K个数并且进行打印

// 求最大的 k 个数并打印 void Print_Top_k(int k) { FILE* fout = fopen("data.txt", "r"); if (fout == NULL) { perror("fopen"); return; } //创建长度为k的数组 int* arr = (int*)malloc(sizeof(int) * k); if (arr == NULL) { perror("malloc"); fclose(fout); return; } // 先读 k 个元素 int n = 0; int x; while (n < k && fscanf(fout, "%d", &x) == 1) { arr[n++] = x; } //如果没有读取元素那么就退出 if (n == 0) { printf("文件没有数据\n"); free(arr); fclose(fout); return; } // 如果文件数据不足 k 个,就按实际数量处理 k = n; // 建成小根堆 BuildMinHeap(arr, k); // 遍历剩余数据 while (fscanf(fout, "%d", &x) == 1) { if (x > arr[0]) { // 比堆顶大,替换堆顶 arr[0] = x; AdjustDown(arr, k, 0); } } //关闭文件 fclose(fout); // 输出堆中元素(此时是小根堆结构,不保证有序) printf("最大的 %d 个数(小根堆结构):\n", k); for (int i = 0; i < k; i++) { printf("%d ", arr[i]); } printf("\n"); //这里采用简单选择排序,因为处理的元素个数比较小,对k个元素进行完整排序 for (int i = 0; i < k - 1; i++) { for (int j = i + 1; j < k; j++) { if (arr[j] > arr[i]) { swap(&arr[i], &arr[j]); } } } //排序后打印 printf("排序后,从大到小:\n"); for (int i = 0; i < k; i++) { printf("%d ", arr[i]); } printf("\n"); free(arr); arr = NULL; }

主函数测试:

int main() { CreatFile(); // 生成 data.txt int k = 0; printf("请输入 k:"); scanf("%d", &k); if (k <= 0) { printf("k 必须大于 0\n"); return 1; } Print_Top_k(k); return 0; }

相关新闻

Agent稳定运行的工程基石:Harness设计与实践拆解

Agent稳定运行的工程基石:Harness设计与实践拆解

先交代一个背景。我们团队最早做某自动化运维 Agent 时&#xff0c;第一版代码就是一个while True循环里反复调用大模型、执行工具、再喂回模型。前三天跑得挺顺&#xff0c;第四天它突然开始疯狂调用同一个内部接口&#xff0c;把下游服务打到限流。查了半天才发现&#xff0c…

2026/10/20 5:04:57 阅读更多 →
Strata部署Qwen3.8-Flash-Next:低显存轻量模型推理实战

Strata部署Qwen3.8-Flash-Next:低显存轻量模型推理实战

前阵子我想把一个3.8B级别的轻量模型做成内部可用的推理服务&#xff0c;要求很简单&#xff1a;普通显卡能跑、接口要像模像样、并发一多也不能崩。折腾了一轮部署方案之后&#xff0c;真正让我愿意留下来的组合就是Strata跑Qwen3.8-Flash-Next。如果你也在找低显存设备上的私…

2026/10/20 5:04:57 阅读更多 →
AI切片 vs 人工剪辑:短视频批量制作成本与效率全对比

AI切片 vs 人工剪辑:短视频批量制作成本与效率全对比

咱们团队最近有个项目卡在“这视频到底怎么剪”上——四小时的单场活动素材&#xff0c;最终要交付16条对标短视频。有人提了一嘴用AI切片工具先过一遍&#xff0c;剪辑组老师傅不乐意了&#xff0c;觉得机器切出来的东西还得返工&#xff0c;不如直接人工来。两边掰扯了两天&a…

2026/10/20 5:04:57 阅读更多 →

最新新闻

原生JavaScript实现贪吃蛇:核心逻辑与Canvas渲染实战

原生JavaScript实现贪吃蛇:核心逻辑与Canvas渲染实战

最近整理硬盘上的旧文件夹&#xff0c;翻出一个好几年前写的JavaScript贪吃蛇。当时是某段时间练手用的&#xff0c;代码写得很粗糙&#xff0c;注释也不全&#xff0c;但核心逻辑基本完整&#xff0c;跑起来没有问题。这几天花时间把代码理清爽、补上注释、顺手修掉几个当年没…

2026/10/20 5:38:13 阅读更多 →
大模型长期记忆系统设计:压缩、去重、遗忘、衰减与冲突处理

大模型长期记忆系统设计:压缩、去重、遗忘、衰减与冲突处理

1. 项目概述&#xff1a;为什么“长期记忆”不是加个数据库就完事了&#xff1f;“大模型长期记忆系统设计&#xff1a;记忆压缩、去重、动态遗忘、时间衰减与冲突处理应用实践24.0”——这个标题里没有一个词是虚的&#xff0c;全是实打实踩过坑、调过参、被线上事故教育过的硬…

2026/10/20 5:38:13 阅读更多 →
物理层实战指南:从奈奎斯特准则到眼图诊断的工程拆解

物理层实战指南:从奈奎斯特准则到眼图诊断的工程拆解

1. 这不是“背书式”复习&#xff0c;而是用工程师视角重解物理层你有没有试过翻开《计算机网络》第2章——物理层&#xff0c;满页都是“奈奎斯特准则”“香农公式”“曼彻斯特编码”“基带传输”“频带传输”……字都认识&#xff0c;连起来却像在读天书&#xff1f;更扎心的…

2026/10/20 5:38:13 阅读更多 →
字符田字格绘制

字符田字格绘制

一、实验目的 掌握 Python 的 print() 输出方法&#xff0c;理解空格和换行对字符图形的影响。掌握字符串拼接与重复运算&#xff0c;实现边框和格内空白的构造。理解嵌套循环的执行过程&#xff0c;使用函数完成可调整大小的网格绘制。 二、实验环境 本次验证环境为 macOS&…

2026/10/20 5:38:13 阅读更多 →
Windows内网提权完全指南:配置错误、漏洞路径与加固实战

Windows内网提权完全指南:配置错误、漏洞路径与加固实战

1. 为什么安全评估绕不开Windows内网提权做了这么多年Windows环境的安全评估和加固&#xff0c;我越来越觉得提权这块知识是所有系统管理员和运维同学绕不过去的坎。很多人觉得“提权”就是攻击者的专属话题&#xff0c;实际恰恰相反&#xff0c;一个不清楚内网中有哪些提权路径…

2026/10/20 5:38:13 阅读更多 →
Agent记忆系统完全指南:从架构拆解到工程实战

Agent记忆系统完全指南:从架构拆解到工程实战

做智能体&#xff08;Agent&#xff09;的项目时间越长&#xff0c;我越觉得“记忆系统”是最容易被低估、却又最能拉开体验差距的一块。大家平时聊天都喜欢盯着模型参数、工具调用、提示词模板&#xff0c;真正让一个 Agent 从“答非所问”变得“像个靠谱的同事”的&#xff0…

2026/10/20 5:37:12 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →