Python使用heapq实现小顶堆(TopK大)、大顶堆(BtmK小)

Python使用heapq实现小顶堆(TopK大)、大顶堆(BtmK小) | 四号程序员

Python使用heapq实现小顶堆(TopK大)、大顶堆(BtmK小)

需1求:给出N长的序列,求出TopK大的元素,使用小顶堆,heapq模块实现。

01import heapq
02import random
03 
04class TopkHeap(object):
05    def __init__(self, k):
06        self.k = k
07        self.data = []
08 
09    def Push(self, elem):
10        if len(self.data) < self.k:
11            heapq.heappush(self.data, elem)
12        else:
13            topk_small = self.data[0]
14            if elem > topk_small:
15                heapq.heapreplace(self.data, elem)
16 
17    def TopK(self):
18        return [x for x in reversed([heapq.heappop(self.data) for x in xrange(len(self.data))])]
19 
20if __name__ == "__main__":
21    print "Hello"
22    list_rand = random.sample(xrange(1000000), 100)
23    th = TopkHeap(3)
24    for i in list_rand:
25        th.Push(i)
26    print th.TopK()
27    print sorted(list_rand, reverse=True)[0:3]

上面的用heapq就能轻松搞定。

变态的需求来了:给出N长的序列,求出BtmK小的元素,即使用大顶堆。

heapq在实现的时候,没有给出一个类似Java的Compartor函数接口或比较函数,开发者给出了原因见这里:http://code.activestate.com/lists/python-list/162387/

于是,人们想出了一些很NB的思路,见:http://stackoverflow.com/questions/14189540/python-topn-max-heap-use-heapq-or-self-implement

我来概括一种最简单的:

将push(e)改为push(-e)、pop(e)改为-pop(e)。

也就是说,在存入堆、从堆中取出的时候,都用相反数,而其他逻辑与TopK完全相同,看代码:

01class BtmkHeap(object):
02    def __init__(self, k):
03        self.k = k
04        self.data = []
05 
06    def Push(self, elem):
07        # Reverse elem to convert to max-heap
08        elem = -elem
09        # Using heap algorighem
10        if len(self.data) < self.k:
11            heapq.heappush(self.data, elem)
12        else:
13            topk_small = self.data[0]
14            if elem > topk_small:
15                heapq.heapreplace(self.data, elem)
16 
17    def BtmK(self):
18        return sorted([-x for x in self.data])

经过测试,是完全没有问题的,这思路太Trick了……

posted on 2013-09-16 19:44  lexus 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lexus/p/3325000.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值