heapq模块实现了一个适用于python列表的最小堆排序算法
import heapq
date = [19,9,4,10,11]
heap = []
使用heappush(),往堆中插入一个元素
for n in date:
heapq.heappush(heap,n)
使用heapify(),重新排序整个列表
heapq.heapify(date)
print date
heappop(),提取出第一个元素也就是最小的元素,并对剩下的元素堆排序
num = heapq.heappop(date)
print date,num
heapreplace()的作用就是heappop()+heappush()
heapq.heapreplace(date,0)
print date
在某个集合中找出最大或者最小的N个元素,可以用nlargest()和nsmallest()
nums = [1,8,9,45,15,36,6,19,46,-5,66,34,67,12,10,99,39,71]
maxnums = heapq.nlargest(3,nums)
minnums = heapq.nsmallest(3,nums)
print maxnums,minnums
还可以接受一个参数key,从而允许它们工作在更加复杂的数据结构之上
portfolio = [
{'name':'IBM','shares':100,'price':91.1},
{'name':'AAPL','shares':150,'price':543.22},
{'name':'FB','shares':200,'price':21.9},
{'name':'HPQ','shares':35,'price':31.75},
{'name':'YHOO','shares':45,'price':16.35},
{'name':'ACME','shares':75,'price':115.65},
]
cheap = heapq.nlargest(3,portfolio,key=lambda s:s['price'])
expensive = heapq.nsmallest(3,portfolio,key=lambda s:s['price'])
print cheap,expensive
当所要找的元素数量相对较小时(N>1),函数nlargest()和nsmallest()才是最适合的,且实际实现会根据使用它们的方式而有所不同,可能会相应作出一些优化措施,比如当N的大小同输入大小很接近时,就会采用排序的方法
print:
[4, 9, 19, 10, 11]
[9, 10, 19, 11] 4
[0, 10, 19, 11]
[99, 71, 67] [-5, 1, 6]
[{'price': 543.22, 'name': 'AAPL', 'shares': 150}, {'price': 115.65, 'name': 'ACME', 'shares': 75}, {'price': 91.1, 'name': 'IBM', 'shares': 100}] [{'price': 16.35, 'name': 'YHOO', 'shares': 45}, {'price': 21.9, 'name': 'FB', 'shares': 200}, {'price': 31.75, 'name': 'HPQ', 'shares': 35}]
在《python cookbook》书中的例子
下面的类利用heapq模块实现了一个简单的优先级队列
class Priorityqueue:
def __init__(self):
self._queue = []
self._index = 0
def push(self,item,priority):
heapq.heappush(self._queue,(-priority,self._index,item))
self._index+=1
def pop(self):
return heapq.heappop(self._queue)[-1]
def __repr__(self):
return str(self._queue)
__str__ = __repr__
class Item:
def __init__(self,name):
self.name = name
def __repr__(self):
return self.name
__str__ = __repr__
q = Priorityqueue()
q.push(Item('foo'),1)
q.push(Item('bar'),5)
q.push(Item('spam'),4)
q.push(Item('grok'),1)
print q
print q.pop()
print q.pop()
print q
print:
[(-5, 1, bar), (-1, 0, foo), (-4, 2, spam), (-1, 3, grok)]
bar
spam
[(-1, 0, foo), (-1, 3, grok)]
在这段代码中队列以元组的形式组成,把priority取负值是为了让队列能够按元素的优先级顺序排序,index的作用是在优先级相同时按人队列时的顺序排列。可以看到元组可以通过其中的元素去比较,一旦比较操作的结果可以确定,就不会再去比较剩下的元素了