Search code examples
pythonindexingpass-by-referencepriority-queue

Update of element's priority in PriorityQueue is not taken into account


from queue import PriorityQueue

pq = PriorityQueue()
x = [20,0]
y = [20,0]
pq.put(x)
pq.put(y)
y[1] = -1
print(x,y) 
while not pq.empty():
    print(pq.get())

The output of the above program is:

[20,0]
[20,-1]

Where as the output should be in ascending order:

[20,-1]
[20,0] 

Solution

  • By mutating the pair after it has been put in the queue, you bypass the priority queue's logic. It is not notified about the update you made.

    If you really have to modify the priority of an element that is already in the queue, then first invalidate it, and add a new element to it that is intended as replacement:

    from queue import PriorityQueue
    
    inf = float("inf")
    pq = PriorityQueue()
    x = [20,0]
    y = [20,0]
    pq.put(x)
    pq.put(y)
    
    # create a copy that has the desired modification
    newy = [y[0], -1]
    pq.put(newy)
    # invalidate the element that was already in the queue
    y[0] = -inf 
    y[1] = -inf
    
    while not pq.empty():
        val = pq.get()
        # ignore invalidated entries
        if val[0] != -inf:
            print(val)
    

    Another approach would be to use heapq instead of queue.PriorityQueue, mutate the element and then call heapify to restore the heap property.

    from heapq import heapify, heappush, heappop
    
    heap = []
    x = [20,0]
    y = [20,0]
    heappush(heap, x)
    heappush(heap, y)
    
    # mutate...
    y[1] = -1
    # ...and heapify
    heapify(heap)
    
    while heap:
        print(heappop(heap))
    

    This looks simpler, but be aware that heapify has a linear time complexity: it visits all elements of the heap.