Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing an arbitrary item from the priority queue

How can I remove an arbitrary item from a priority queue. Suppose I have a PriorityQueue for jobs. I have a job I want to "cancel" so I need to remove it from the queue, how can I do that?

UPDATE

To add to the answer, a related question: https://stackoverflow.com/a/9288081/292291

like image 547
Jiew Meng Avatar asked Feb 15 '12 04:02

Jiew Meng


People also ask

What is the use of remove () method of PriorityQueue class?

The remove () method of PriorityQueue class removes a single instance of the specified element from this queue, only if it is present. o - It is the element to be eliminated from this queue.

What is the use of priority queue?

Priority Queue is an extension of queue with following properties. 1) Every item has a priority associated with it. 2) An element with high priority is dequeued before an element with low priority. 3) If two elements have the same priority, they are served according to their order in the queue.

What happens if calls of remove () exceed the elements present in queue?

Geek, have you ever wondered what will happen if calls of remove () method exceed the elements present in the queue. In this scenario, it will continue to remove the elements that were there, and thereafter it will not find any element to remove priority-wise, so it will throw an exception which is as follows.

What is the priority of an element?

Every item has a priority associated with it. An element with high priority is dequeued before an element with low priority. If two elements have the same priority, they are served according to their order in the queue.


1 Answers

I'm assuming you're using heapq. The documentation has this to say about this problem, which seems quite reasonable:

The remaining challenges revolve around finding a pending task and making changes to its priority or removing it entirely. Finding a task can be done with a dictionary pointing to an entry in the queue.

Removing the entry or changing its priority is more difficult because it would break the heap structure invariants. So, a possible solution is to mark the existing entry as removed and add a new entry with the revised priority.

The documentation provides some basic example code to show how this can be done, which I reproduce here verbatim:

pq = []                         # list of entries arranged in a heap
entry_finder = {}               # mapping of tasks to entries
REMOVED = '<removed-task>'      # placeholder for a removed task
counter = itertools.count()     # unique sequence count

def add_task(task, priority=0):
    'Add a new task or update the priority of an existing task'
    if task in entry_finder:
        remove_task(task)
    count = next(counter)
    entry = [priority, count, task]
    entry_finder[task] = entry
    heappush(pq, entry)

def remove_task(task):
    'Mark an existing task as REMOVED.  Raise KeyError if not found.'
    entry = entry_finder.pop(task)
    entry[-1] = REMOVED

def pop_task():
    'Remove and return the lowest priority task. Raise KeyError if empty.'
    while pq:
        priority, count, task = heappop(pq)
        if task is not REMOVED:
            del entry_finder[task]
            return task
    raise KeyError('pop from an empty priority queue')
like image 132
senderle Avatar answered Nov 15 '22 04:11

senderle