python heap_python topN max heap,使用heapq还是自己实现?

heapq的唯一问题是它没有提供像stdlib中其他所有功能一样的关键功能. (如果你好奇为什么,Raymond Hettinger在

this email中解释过.他是对的,heapq无法提供与其他排序函数相同的接口 – 但原因不会影响你的用例,其中key只是lambda x: – X.)

通常的解决方法是decorate-heap-undecorate.也就是说,将值的修改版本放入按密钥排序的堆中.通常,这意味着以下之一:

>存储密钥(x)而不是x,然后访问unkey(值)而不是值(假设密钥是可逆的).

>存储(key(x),x)而不是x,然后访问值[1]. (这可以打破稳定性,但无论如何,heapq都不会保证稳定性.)

>编写一个实现自定义__le__方法的包装类,然后存储Wrapper(x)而不是x并访问value.value而不是value.

在您的情况下,关键功能是可逆的.所以,只需存储-x和access -value.这和装饰一样微不足道.

尽管如此,无论它有多简单,你都应该写一个包装器,否则你会在某些时候搞砸它.例如,您可以编写一个maxheap来包装heapq中的minheap,如下所示:

import heapq

def heapify(x):

for i in range(len(x)):

x[i] = -x[i]

heapq.heapify(x)

def heappush(heap, item):

heapq.heappush(heap, -item)

def heappop(heap):

return -heapq.heappop(heap)

……等等您需要的任何其他功能.这可能有点痛苦,但是比从头开始实施整个事情要少得多.

当你在它时,你可能想要将堆包装在面向对象的API中,这样你就可以执行heap.push(x)而不是heapq.heappush(heap,x)等.

import heapq

class MaxHeap(object):

def __init__(self, x):

self.heap = [-e for e in x]

heapq.heapify(self.heap)

def push(self, value):

heapq.heappush(self.heap, -value)

def pop(self):

return -heapq.heappop(self.heap)

如果您快速浏览一下ActiveState的配方或PyPI上的模块,您会发现其他人已经为您完成了大部分工作.

或者,您可以将heapq源(它是纯Python)复制并粘贴为maxheapq.py,然后将cmp_lt函数替换为相反的cmp_lt函数. (当然,如果你正在这样做,那么修改cmp_lt以获取一个关键参数,并且修改所有其他函数以传递密钥时,可能同样容易,当然也更清楚一些.它将不再普遍适用,因为它不能通常保证只调用一次密钥.)

如果你真的想要危险地生活(你不应该),你甚至可以将其打包:

import heapq

def cmp_gt(x, y):

return y < x if hasattr(y, '__lt__') else not (x <= y)

heapq.cmp_lt = cmp_gt

但是你不想在实际代码中这样做.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值