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
但是你不想在實際代碼中這樣做.
總結
以上是生活随笔為你收集整理的python heap_python topN max heap,使用heapq还是自己实现?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 乡下开服装店赚钱吗 算是比较好的项目了
- 下一篇: 单链表的基本操作_数据结构-单链表的基本