news 2026/8/5 7:00:30

海量数据中找出最大的前100个(find_topk)最小堆算法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
海量数据中找出最大的前100个(find_topk)最小堆算法

我来帮你实现这个寻找前100个最大数据的算法。这个算法的时间复杂度是O(n log 100),空间复杂度是O(100)。

C++实现

#include<iostream>#include<vector>#include<queue>#include<functional>#include<random>usingnamespacestd;// 寻找前k个最大元素的算法vector<int>findTopK(constvector<int>&nums,intk){if(nums.size()<=k){vector<int>result(nums.begin(),nums.end());returnresult;}// 创建最小堆priority_queue<int,vector<int>,greater<int>>minHeap;// 步骤1: 插入前k个元素for(inti=0;i<k;i++){minHeap.push(nums[i]);}// 步骤2-3: 遍历剩余元素,维护堆for(size_t i=k;i<nums.size();i++){if(nums[i]>minHeap.top()){minHeap.pop();// 弹出堆顶minHeap.push(nums[i]);// 插入当前元素}}// 步骤4: 堆中元素即为前k个最大数据vector<int>result;while(!minHeap.empty()){result.push_back(minHeap.top());minHeap.pop();}returnresult;}intmain(){// 生成测试数据vector<int>data(1000);random_device rd;mt19937gen(rd());uniform_int_distribution<>dis(1,10000);for(inti=0;i<1000;i++){data[i]=dis(gen);}intk=100;vector<int>topK=findTopK(data,k);cout<<"前"<<k<<"个最大元素:"<<endl;for(size_t i=0;i<topK.size();i++){cout<<topK[i]<<" ";if((i+1)%10==0)cout<<endl;}cout<<endl;return0;}

Python实现

importheapqimportrandomfromtypingimportListdeffind_top_k(nums:List[int],k:int)->List[int]:""" 寻找前k个最大元素的算法 实现步骤: 1. 创建一个最小堆并将前k个数据插入堆中 2. 遍历剩余的数据,如果当前数据比堆顶大,就替换堆顶元素 3. 继续遍历所有数据,确保堆中保留的是最大的k个数据 4. 遍历完成后,堆中的元素就是前k个最大的数据 """iflen(nums)<=k:returnsorted(nums,reverse=True)# 步骤1: 创建最小堆并插入前k个元素min_heap=nums[:k]heapq.heapify(min_heap)# 建立最小堆# 步骤2-3: 遍历剩余元素,维护堆fornuminnums[k:]:ifnum>min_heap[0]:# 如果当前元素比堆顶大# 弹出堆顶,插入当前元素heapq.heapreplace(min_heap,num)# 步骤4: 堆中元素即为前k个最大数据# 堆是最小堆,需要排序后返回result=sorted(min_heap,reverse=True)returnresultdeffind_top_k_alternative(nums:List[int],k:int)->List[int]:"""另一种实现方式,更清晰地体现算法步骤"""iflen(nums)<=k:returnsorted(nums,reverse=True)# 步骤1: 创建最小堆并插入前k个元素min_heap=[]foriinrange(k):heapq.heappush(min_heap,nums[i])# 步骤2-3: 遍历剩余数据foriinrange(k,len(nums)):ifnums[i]>min_heap[0]:# 比堆顶大# 我就往堆里面插heapq.heappop(min_heap)# 弹出堆顶heapq.heappush(min_heap,nums[i])# 插入当前数据# 步骤4: 返回结果returnsorted(min_heap,reverse=True)defmain():# 生成测试数据random.seed(42)data=[random.randint(1,10000)for_inrange(1000)]k=100# 使用方法1top_k=find_top_k(data,k)print(f"前{k}个最大元素:")fori,numinenumerate(top_k,1):print(f"{num:6d}",end=" ")ifi%10==0:print()print()# 验证结果正确性sorted_data=sorted(data,reverse=True)[:k]print(f"算法结果是否正确:{top_k==sorted_data}")# 使用方法2top_k2=find_top_k_alternative(data,k)print(f"方法2结果是否正确:{sorted(top_k2)==sorted(top_k)}")if__name__=="__main__":main()

算法复杂度分析

  • 时间复杂度: O(n log k),其中n是总数据量,k=100
  • 空间复杂度: O(k),只需要维护大小为100的堆

关键点说明

  1. 使用最小堆的原因:我们想要最大的k个元素,使用最小堆可以让我们在O(1)时间内知道当前堆中最小的元素
  2. 堆顶的作用:堆顶始终是当前堆中最小的元素,也就是第k大的候选者
  3. 替换条件:只有当新元素大于堆顶时,才进行替换,确保堆中始终是见过的最大的k个元素
  4. “我就往堆里面插”:这个操作在代码中体现为
    "heapq.heapreplace()"或先pop再push的操作

两种实现方式都可以,Python版本提供了两种写法:

    “find_top_k”:使用
    “heapq.heapreplace()”,更简洁

    “find_top_k_alternative”:分步操作,更清晰地体现算法步骤

    版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
    网站建设 2026/8/3 12:44:43

    告别“大海捞针“:InternLM2.5-1M如何让百万字长文本变得触手可及?

    还记得那个让你抓狂的场景吗&#xff1f;一份200页的合同摆在眼前&#xff0c;你需要在密密麻麻的条款中找出那个关键的风险点。或者面对上百篇学术论文&#xff0c;想要快速梳理出核心观点却无从下手。现在&#xff0c;这些困扰将成为过去式。 【免费下载链接】InternLM Offic…

    作者头像 李华
    网站建设 2026/8/5 16:33:58

    如何快速解决PyTorch Geometric TUDataset加载问题:5个实战技巧

    如何快速解决PyTorch Geometric TUDataset加载问题&#xff1a;5个实战技巧 【免费下载链接】pytorch_geometric Graph Neural Network Library for PyTorch 项目地址: https://gitcode.com/GitHub_Trending/py/pytorch_geometric PyTorch Geometric TUDataset是图神经网…

    作者头像 李华
    网站建设 2026/8/3 11:03:21

    BetterDiscord 深度定制指南:打造属于你的专属聊天体验

    BetterDiscord 深度定制指南&#xff1a;打造属于你的专属聊天体验 【免费下载链接】BetterDiscordApp Better Discord App enhances Discord desktop app with new features. 项目地址: https://gitcode.com/gh_mirrors/be/BetterDiscordApp 你是否曾经觉得 Discord 的…

    作者头像 李华
    网站建设 2026/8/5 16:51:17

    BUUCTF[jarvisoj_level2_x64]

    步骤使用checksec查看使用ida(pro)打开根进vulnerable_function函数依旧是栈溢出这道题我们无法使用上一题的32位来直接使用plt表来跳转到system,所以我们使用ROPgadget使用指令 ROPgadget --binary 文件名 来获取信息这里可以查看到pop rdi;ret的地址在64位中前几个参数我们是…

    作者头像 李华
    网站建设 2026/8/3 12:56:30

    前端如何通过FormData实现大文件分片上传?

    网工大三党文件上传救星&#xff1a;原生JS实现10G大文件上传&#xff08;Vue3IE8兼容&#xff09; 兄弟&#xff0c;作为刚入坑网络工程的山西老狗&#xff0c;我太懂你现在的处境了——老师要10G大文件上传的毕业设计&#xff0c;网上找的代码全是“断头路”&#xff0c;后端…

    作者头像 李华
    网站建设 2026/8/4 20:33:03

    .NET WebForm如何支持大文件上传的进度显示?

    毕业设计&#xff1a;企业级文件传输系统方案探索 在毕业设计选题阶段&#xff0c;我结合自身兴趣与计算机专业所学&#xff0c;确定了企业级文件传输系统这一课题。近期&#xff0c;我在网上搜索相关资料、参与论坛交流、加入多个QQ群和微信群&#xff0c;但收获不尽如人意。很…

    作者头像 李华