ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Priority Queue
Submitter: simo salminen (other recipes)
Last Updated: 2002/05/03
Version no: 1.2
Category: Algorithms

 

4 stars 3 vote(s)


Description:

Thread-safe priority queue using Queue.Queue

Source: Text Source

import Queue

class PriorityQueue(Queue.Queue):
    def _put(self, item):
        data, priority = item
        self._insort_right((priority, data))
        
    def _get(self):
        return self.queue.pop(0)[1]

    def _insort_right(self, x):
        """Insert item x in list, and keep it sorted assuming a is sorted.
        
        If x is already in list, insert it to the right of the rightmost x.       
        """
        a = self.queue
        lo = 0        
        hi = len(a)
        
        while lo < hi:
            mid = (lo+hi)/2
            if x[0] < a[mid][0]: hi = mid
            else: lo = mid+1
        a.insert(lo, x)

def test():
    pq = PriorityQueue()

    pq.put(('b', 1))
    pq.put(('a', 1))
    pq.put(('c', 1))
    pq.put(('z', 0))
    pq.put(('d', 2))

    while not pq.empty():
        print pq.get(),   
    
test() # prints z b a c d

Discussion:



Add comment

Number of comments: 10

pop or get?, Lee Harr, 2002/02/22
Queue.Queue does not have a pop() method. It does however have a get() method.
Add comment

output, Lee Harr, 2002/02/22
For me, this outputs: z b a c d
Add comment

output, simo salminen, 2002/05/03
typo corrected.
Add comment

pop method, simo salminen, 2002/05/03
I don't quite understand what you mean. the pop() call in _get-calls the internal queue-data structure, which is python list.
Add comment

using bisect.insort_right(), Mark Moraes, 2002/06/11
Would using bisect.insort_right() cause problems? i.e.

    def _put(self, item):
        bisect.insort_right(self.queue, item)
seems to work nicely.
I also found a 'top' method useful:
    def top(self):
        "non-destructively return smallest element in pqueue"
        try:
            x = self.queue[0]
        except IndexError:
            x = None
        return x

Add comment

bisect.insort_right will not work, Chris Perkins, 2002/10/28
Using bisect.insort_right as you suggest would not work.
Assuming item is a tuple of (priority, data), then it would be inserted amongst other items in the queue with the same priority, but sorted by the value of its data, rather than by its arrival time.
You may be able to hack around this with something like:

self.queue.insert(bisect.bisect_right(self.queue, (priority, sys.maxint)), (priority, data))
if the data are all integers.
Add comment

bisection, greg klanderman, 2003/01/31
why bother with bisection if you're just going to use an O(n) insert?
Add comment

Why not use a heapqueue, Thomas Ahle, 2007/06/05
Like this:

from Queue import Queue
from heapq import heappush, heappop

class PriorityQueue(Queue):
    # Initialize the queue representation
    def _init(self, maxsize):
        self.maxsize = maxsize
        self.queue = []
    
    # Put a new item in the queue
    def _put(self, item):
        return heappush(self.queue, item)
    
    # Get an item from the queue
    def _get(self):
        return heappop(self.queue)

if __name__ == "__main__":
    q = PriorityQueue()
    q.put((2,"a"))
    q.put((0,"b"))
    q.put((1,"c"))
    q.put((2,"d"))
    q.put((1,"e"))
    while not q.empty():
        print q.get()
prints b, c, e, a, d
Add comment

Using bisect module, Giles Brown, 2007/06/21
I don't really understand the maths of heapq, but it doesn't seem to maintain the existing ordering. In fact if you use the example from the published 2nd edition cookbook, if you insert a series of items with the same time.time() value they get ordered according to their (undecorated) item value which is not so good. And I'm a bit bothered by not re-using the bisect algorithm, so here is a version that doesn't sort on item value, but does use the bisect module.

from Queue import Queue
from bisect import bisect_left

class PriorityQueue(Queue):

    def _init(self, maxsize):
        self.maxsize = maxsize
        # Python 2.5 uses collections.deque, but we can't because
        # we need insert(pos, item) for our priority stuff
        self.queue = []

    def put(self, item, priority=0, block=True, timeout=None):
        """Puts an item onto the queue with a numeric priority (default is zero).
        
        Note that we are "shadowing" the original Queue.Queue put() method here.
        """
        Queue.put(self, (priority, item), block, timeout)

    def _put(self, item):
        """Override of the Queue._put to support prioritisation."""
        # Priorities must be integers!
        priority = int(item[0])

        # Using a tuple (priority+1,) finds us the correct insertion
        # position to maintain the existing ordering.
        self.queue.insert(bisect_left(self.queue, (priority+1,)), item)

    def _get(self):
        """Override of Queue._get().  Strips the priority."""
        return self.queue.pop(0)[1]

Add comment

Priority Queue Semantics, David Arnold, 2008/05/18
Maintaining the existing ordering isn't usually what a priority queue does. If you have several objects with the same priority, it doesn't matter what order you address them in. (After all, they have the /same/ priority.) ER-style priority, like your example, is a different strategy (items that have the same value for their priority don't technically have the same 'priority'). Often, applications that require priority queues (like implementations of Dijkstra's algorithm, or A* search) would much rather have the performance boost of a heap versus the maintenance of first-come ordering. (heap is O(logN) to insert, list insort is O(NlogN))

It's a trade-off of performance versus a specific semantic. I am curious: what situation did you create this PriorityQueue for that demanded first-come ordering?
Add comment



Highest rated recipes:

1. A simple XML-RPC server

2. Web service accessible ...

3. IPy Notify

4. Changing return value ...

5. Quantum Superposition

6. Pickle objects under ...

7. Generalized delegates ...

8. Reorder a sequence (uses ...

9. Setting Win32 System ...

10. ObjectMerger




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.