手记

python常用模块学习记录 -- heapq

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的作用是在优先级相同时按人队列时的顺序排列。可以看到元组可以通过其中的元素去比较,一旦比较操作的结果可以确定,就不会再去比较剩下的元素了

个人博客
http://www.greenblog.cn/

2人推荐
随时随地看视频
慕课网APP