'Removing an item from a priority queue
In Python, the heapq
module provides a priority queue.
It has methods for inserting and popping items.
How do you remove an item that you have inserted that is not the lowest priority from the queue?
(Alternative recipes for doing this using alternative other collections are welcome too)
Solution 1:[1]
The heapq
module uses standard Python lists as underlying data structure, so you can just use the standard list
method remove()
and heapify()
again after this. Note that this will need linear time though.
# Create example data and heapify
a = range(10)
a.reverse()
heapq.heapify(a)
print a
# remove an element and heapify again
a.remove(5)
heapq.heapify(a)
print a
You could improve the performance of heapifying again by using the undocumented function heapify._siftup()
, but the whole process will still be O(n) since list.remove()
is O(n).
Solution 2:[2]
If you know the location of the item you wish to remove, you can do the following:
a[k] = a.pop()
heapq.heapify(a)
The first step is now O(1) time, and the second can be made O(log(N)) by using the undocumented data. Of course, it's still O(N) to find k if you don't have it already.
Solution 3:[3]
This log(N) function works for me:
def heapq_remove(heap, index):
"""Remove item from heap"""
# Move slot to be removed to top of heap
while index > 0:
up = (index + 1) / 2 - 1
heap[index] = heap[up]
index = up
# Remove top of heap and restore heap property
heapq.heappop(heap)
Solution 4:[4]
There is a data structure called a treap which is a priority queue and binary tree combined. (tree-heap). It allows for log-n search which might help you.
There's a Python treap implementation on PyPi.. ;)
Solution 5:[5]
If you don't want an O(n) routine you need to use internal _siftup
and _siftdown
(yes you need to use both because after the swap the element may need swim down as it may need to float up). You decide if that's deterrent for you or not, but here it goes.
import heapq
# The removal function using internal functions
def remove_item(heap, val):
if not heap:
return
try:
i = heap.index(val)
except ValueError:
return
if i < len(heap) - 1:
heap[i] = heap[-1]
heap.pop()
if i < len(heap):
heapq._siftup(heap, i)
heapq._siftdown(heap, 0, i)
# Initial state
a = range(30)
a.reverse()
heapq.heapify(a)
print(a)
# The removal
remove_item(a, 15)
print(a)
Kudos to Duncan: https://stackoverflow.com/a/10163422/292502
Solution 6:[6]
had this problem on my project
using search algorithms
,
here is the answer:
queue_name = PriorityQueue()
queue_name.queue.remove(item_to_be_removed)
Say you had a tuple
as an item then an example would be:
queue_name.queue.remove((number, item_name))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | DaveShaw |
Solution 3 | |
Solution 4 | |
Solution 5 | Csaba Toth |
Solution 6 | FLAK-ZOSO |