zoukankan      html  css  js  c++  java
  • 【python cookbook】【数据结构与算法】5.实现优先级队列

    问题:要实现一个队列,它能够以给定的优先级对元素排序,且每次pop操作时都会返回优先级最高的那个元素;

    解决方案:采用heapq模块实现一个简单的优先级队列

    # example.py
    #
    # Example of a priority queue
    
    import 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]
    
    # Example use
    class Item:
        def __init__(self, name):
            self.name = name
        def __repr__(self):
            return 'Item({!r})'.format(self.name)
    
    q = PriorityQueue()
    q.push(Item('foo'), 1)
    q.push(Item('bar'), 5)
    q.push(Item('spam'), 4)
    q.push(Item('grok'), 1)
    
    print("Should be bar:", q.pop())
    print("Should be spam:", q.pop())
    print("Should be foo:", q.pop())
    print("Should be grok:", q.pop())
    Python 3.4.0 (v3.4.0:04f714765c13, Mar 16 2014, 19:24:06) [MSC v.1600 32 bit (Intel)] on win32
    Type "copyright", "credits" or "license()" for more information.
    >>> ================================ RESTART ================================
    >>> 
    Should be bar: Item('bar')
    Should be spam: Item('spam')
    Should be foo: Item('foo')
    Should be grok: Item('grok')
    >>> 

    可以看出:第一次执行pop()操作时返回的元素具有最高的优先级;对于相同优先级的两个元素(foo和gork)返回的顺序同它们插入到队列时的顺序相同。

    在这段代码中,队列以元组(-priority, self._index, item)的形式组成,priority取负值是为了队列按照从高到低的顺序排列,这和堆默认的从小到大的排序相反。

    变量index的作用是对相同优先级的元素以适当的顺序排列,特别对同优先级的元素间做比较操作时扮演了重要的角色。

    Item实例无法进行次序比较:

    a=Item('foo')
    b=Item('bar')
    print('a<b: ',a<b)
    >>> 
    Traceback (most recent call last):
      File "D:4autotests2scriptpython-cookbookpython-cookbook-mastersrc15.implementing_a_priority_queueexample.py", line 27, in <module>
        print('a<b: ',a<b)
    TypeError: unorderable types: Item() < Item()
    >>> 

    如果以元组(priority,  item)的形式来表示元素,只要优先级不同,就可进行比较:

    a=(1,Item('foo'))
    b=(5,Item('bar'))
    c=(1,Item('gork'))
    print('a<b: ',a<b)
    print('a<c: ',a<c)
    >>> 
    a<b:  True
    Traceback (most recent call last):
      File "D:4autotests2scriptpython-cookbookpython-cookbook-mastersrc15.implementing_a_priority_queueexample.py", line 29, in <module>
        print('a<c: ',a<c)
    TypeError: unorderable types: Item() < Item()
    >>> 

    引入额外的索引值,以(priority, index, item)的方式建立元组,就可以避免相同优先级无法比较的问题,因为没有哪两个元组会有相同的index值;

    a=(1,0,Item('foo'))
    b=(5,1,Item('bar'))
    c=(1,2,Item('gork'))
    print('a<b: ',a<b)
    print('a<c: ',a<c)
    >>> 
    a<b:  True
    a<c:  True
    >>>

    如果想将这个队列用于线程间通信,还需要增加适当的锁和信号机制。

  • 相关阅读:
    2017沈阳站 Tree
    P2146 [NOI2015]软件包管理器
    hdu3307 欧拉函数
    poj 3126 Prime Path bfs
    CSL的字符串
    P1045 麦森数
    洛谷 P1338 末日的传说
    树链剖分
    SQL[Err] ORA-00933: SQL command not properly ended
    Postman 快速入门之脚本
  • 原文地址:https://www.cnblogs.com/apple2016/p/5744620.html
Copyright © 2011-2022 走看看