用Python实现一个优先级队列(Priority Queue)

堆(Heap)

在实现一个优先队列以前,先简单介绍 heap(堆)的概念。堆,是对于每个父节点上的值都小于或等于子节点的值的二叉树。此外,一个堆必须是一个完整的二叉树,除了最底层其余每一级必须是被完整填充的。所以,堆的最重要的一个特色就是:首项heap[0]老是最小的一项html

而堆化(heapify)则是将一个二叉树转化为一个堆数据结构的过程。在Python中,咱们能够用自带heapq模块中的heapify(x)函数来实现将一个列表 x 转化为一个堆。时间复杂度为线性O(N). 代码以下:python

>>> import heapq
>>> x = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
>>> heap = list(x)
>>> heapq.heapify(heap)
>>> heap
[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]

heap 是被"堆化"后的列表,heap[0] = -4为最小项。注意:此时heap 的数据类型还是一个listapi

另外,能够用heappop(), heappush()heapreplace()等方法来对一个堆列表进行操做。例如,heappop()会从堆列表中拿出并返回最小项,而且使堆保持不变(即heap[0]仍为最小项)。数据结构

>>> heapq.heappop(heap)
-4
>>> heapq.heappop(heap)
1
>>> heapq.heappop(heap)
2
>>> heap
[2, 7, 8, 23, 42, 37, 18, 23]

优先级队列(Priority Queue)

优先级队列的特色:app

  • 给定一个优先级(Priority)
  • 每次pop操做都会返回一个拥有最高优先级的项

代码以下:函数

import heapq

class PriorityQueue(object):
    def __init__(self):
        self._queue = []        #建立一个空列表用于存放队列
        self._index = 0        #指针用于记录push的次序
    
    def push(self, item, priority):
        """队列由(priority, index, item)形式的元祖构成"""
        heapq.heappush(self._queue, (-priority, self._index, item)) 
        self._index += 1
        
    def pop(self):
        return heapq.heappop(self._queue)[-1]    #返回拥有最高优先级的项

class Item(object):
    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'), 5)
    q.push(Item('bar'), 1)
    q.push(Item('spam'), 3)
    q.push(Item('grok'), 1)
    for i in range(4):
        print(q._queue)
        print(q.pop())

对队列进行4次pop()操做,打印结果以下:学习

[(-5, 0, Item: 'foo'), (-1, 1, Item: 'bar'), (-3, 2, Item: 'spam'), (-1, 3, Item: 'grok')]
Item: 'foo'
[(-3, 2, Item: 'spam'), (-1, 1, Item: 'bar'), (-1, 3, Item: 'grok')]
Item: 'spam'
[(-1, 1, Item: 'bar'), (-1, 3, Item: 'grok')]
Item: 'bar'
[(-1, 3, Item: 'grok')]
Item: 'grok'

能够观察出pop()是如何返回一个拥有最高优先级的项。对于拥有相同优先级的项(bar和grok),会按照被插入队列的顺序来返回。代码的核心是利用heapq模块,以前已经说过,heapq.heappop()会返回最小值项,所以须要把 priority 的值变为负,才能让队列将每一项按从最高到最低优先级的顺序级来排序。spa

参考文献:

  1. Python 3.6 Documentation
  2. Python Cookbook (3rd), O'Reilly.

声明

原创文章,仅用于我的学习及参考,禁止转载。一切解释权归原做者全部。文中若有错误或不足之处请及时指出。指针

相关文章
相关标签/搜索