Python實用技法第4篇:實現優先級隊列

上一篇文章: Python實用技法第3篇:找到最大或最小的N個元素
下一篇文章: Python實用技法第5篇:一鍵多值字典

一、需求🙀

咱們想要實現一個隊列,它可以以給定的優先級來對元素排序,且每次pop操做時都會返回優先級最高的那個元素

二、解決方案😸

利用heapq模塊實現

代碼:segmentfault

import heapq

#利用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]

class Item:
    def __init__(self,name):
        self.name=name

    def __repr__(self):
        return 'Item({!r})'.format(self.name)

if __name__ == '__main__':
    q=PriorityQueue()
    q.push(Item('foo'),1)
    q.push(Item('bar'),5)
    q.push(Item('spam'),4)
    q.push(Item('grok'),1)

    print(q.pop())
    print(q.pop())
    #具備相同優先級的兩個元素,返回的順序同它們插入到隊列時的順序相同
    print(q.pop())
    print(q.pop())

運行結果:app

Item('bar')
Item('spam')
Item('foo')
Item('grok')
上面的代碼核心在於heapq模塊的使用。函數heapq.heapqpush()以及heapq.heapqpop()分別實現將元素從列表_queue中插入和移除,且保證列表中第一個元素的優先級最低。heappop()方法老是返回【最小】的元素,所以這就是讓隊列能彈出正確元素的關鍵。此外,因爲push和pop操做的複雜度都是O(logN),其中N表明堆中元素的數量,所以就算N的值很大,這些操做的效率也很是高。

上面代碼中,隊列以元組(-priority ,index,item)的形式組成。把priority取負值是爲了讓隊列可以按照元素的優先級從高到底的順序排列。函數

變量index的做用是爲了將具備相同優先級的元素以適當的順序排列。經過維護一個不斷遞增的索引,元素將以它們如隊列時的順序來排列。爲了說明index的做用,看下面實例:spa

代碼:code

class Item:
    def __init__(self,name):
        self.name=name

    def __repr__(self):
        return 'Item({!r})'.format(self.name)

if __name__ == '__main__':
    a=(1,Item('foo'))
    b=(5,Item('bar'))
    #下面一句打印True
    print(a<b)


    c=(1,Item('grok'))
    #下面一句會報錯:TypeError: '<' not supported between instances of 'Item' and 'Item'
    print(c<a)


    d=(1,0,Item('foo'))
    e=(5,1,Item('bar'))
    f=(1,2,Item('grok'))
    #下面一句打印True
    print(d<e)
    #下面一句打印True
    print(d<f)
上一篇文章: Python實用技法第3篇:找到最大或最小的N個元素
下一篇文章: Python實用技法第5篇:一鍵多值字典
相關文章
相關標籤/搜索