【数据结构/堆排序】从大批量数据中快速查找前N个最大值

  问题:给出一堆大批量数据(比如10亿),如何从中快速查找出前N个最大值?
  解决方案:采用最小堆的形式。先取出N个数据生成最小堆,然后再取出后面的值依次与堆顶比较,比堆顶小,则继续;比堆顶大,则交换值,并更新最小堆,直到所有值全部比较完,最后生成的最小堆就是最大的N个数据。
  最小堆概念:最小堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节点的值。如下图所示,即有节点2、节点3大于等于节点1;节点4、节点5大于等于节点2;节点6、节点7大于等于节点3。

最小堆的实例如下所示:

下面,我们通过Python代码来实现利用最小堆查找出数据的前N个最大值。
最小堆文件 MinHeap.py

class MinHeap():
    def parent(self,n):
        return (n-1)//2
    def leftChild(self,n):
        return 2*n+1
    def rightChild(self,n):
        return 2*n+2

    #将list的前n个值构建为最小堆
    def build_min_heap(self,n,list):
        for i in range(n):
            t=i;
            while (t!=0 and (list[self.parent(t)] > list[t])):
                temp = list[t]
                list[t] = list[self.parent(t)]
                list[self.parent(t)] = temp
                t = self.parent(t)
    #将数据与堆顶进行比较
    def adjust_heap(self,i,n,list):
        if(list[i]<list[0]):
            return
        #置换堆顶
        temp = list[i];
        list[i] = list[0];
        list[0] = temp;
        #调整最小堆
        t=0
        while(self.leftChild(t)<n and list[t]>list[self.leftChild(t)])or 
        (self.leftChild(t)<n and list[t]>list[self.leftChild(t)]):
            if ((self.rightChild(t) < n )and (list[self.rightChild(t)] < list[self.leftChild(t)])):
                #右孩子更小,置换右孩子
                temp = list[t];
                list[t] = list[self.rightChild(t)]
                list[self.rightChild(t)] = temp
                t = self.rightChild(t)
            else:
                #否则置换左孩子
                temp = list[t]
                list[t] = list[self.leftChild(t)]
                list[self.leftChild(t)] = temp
                t = self.leftChild(t)
    def findTopN(self,n,list):
        self.build_min_heap(n,list)
        for i in range(len(list)):
            self.adjust_heap(i,n,list)
    def print(self,list):
        print(list)

测试文件 test.py

from topN.MinHeap import MinHeap
if __name__ == "__main__":
    minHeap = MinHeap()
    #第一组测试
    list = [56, 30, 71, 18, 29, 93, 44, 75, 20, 65, 68, 34]
    print("原数组:")
    minHeap.print(list)
    minHeap.findTopN(5, list)
    print("调整后数组:")
    minHeap.print(list)

运行结果

方框中即是原数组中的前5个最大值。
参考:https://mp.weixin.qq.com/s/jES3gqaHfgJXbTgPmUbAqw

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值