Heap/Priority Queue that supports removing arbitrary items and frequency tracking
A generic priority queue for Python - Stack Overflow
Is there a better priority queue?
Peek method in Priority Queue?
Videos
I created a Python heap implementation that supports:
-
Removing any item (not just the root via pop)
-
Tracking the frequency of items so that duplicates are handled efficiently
Source: https://github.com/Ite-O/python-indexed-heap
PyPI: https://pypi.org/project/indexedheap/
What My Project Does
indexedheap is a Python package that provides standard heap operations, insert (push), pop, and peek, along with additional features:
-
Remove any arbitrary item efficiently.
-
Track frequencies of items to handle duplicates.
-
Insert or remove multiple occurrences in a single operation.
-
Iterate over heap contents in sorted order without modifying the heap.
It is designed for scenarios requiring dynamic priority queues, where an item’s priority may change over time Common in task schedulers, caching systems or pathfinding algorithms.
Target Audience
-
Developers needing dynamic priority queues where priorities can increase or decrease.
-
Users who want duplicate-aware heaps for frequency tracking.
-
Engineers implementing task schedulers, caches, simulations or pathfinding algorithms in Python.
Comparison
Python’s built-in heapq vs indexedheap
| Operation | Description |
heapq
|
indexedheap
|
|---|---|---|---|
heappush(heap, item) / insert(value)
| Add an item/value to the heap |
✅ O(log N)
|
✅ O(log N) / (O(1) if item already exists and count is incremented)
|
heappop(heap) / pop()
| Remove and return the root item/value |
✅ O(log N)
|
✅ O(log N)
|
heap[0] / peek()
| Return root item/value without removing it |
✅ Manual (heap[0])
|
✅ O(1)
|
remove(value)
| Remove any arbitrary value | ❌ Not supported |
✅ O(log(N)) for last occurence in heap, O(1) if only decrementing frequency
|
heappushpop(heap, item)
| Push then pop in a single operation |
✅ O(log N)
|
❌ Not directly supported (use insert() + pop())
|
heapreplace(heap, item)
| Pop then push in a single operation |
✅ O(log N)
|
❌ Not directly supported (use pop() + insert())
|
count(value)
| Get frequency of a specific value | ❌ Not supported |
✅ O(1)
|
item in heap / value in heap
| Membership check |
⚠️ O(N) (linear scan)
|
✅ O(1)
|
len(heap)
| Number of elements |
✅ O(1)
|
✅ O(1)
|
to_sorted_list()
| Return sorted elements without modifying heap |
✅ Requires creating a sorted copy of the heap O(N log N)
|
✅ O(N log N)
|
iter(heap)
| Iterate in sorted order |
✅ Requires creating a sorted copy of the heap and iterating over the copy O(N log N))
|
✅ O(N log N)
|
heapify(list) / MinHeap(list), MaxHeap(list)
| Convert list to valid heap |
✅ O(N)
|
✅ O(N)
|
heap1 == heap2
| Structural equality check |
✅ O(N)
|
✅ O(N)
|
Frequency tracking
| Track frequency of items rather than store duplicates | ❌ Not supported | ✅ Yes |
Multi-inserts/removals
| Insert/ remove multiples of an item in a single operation | ❌ Not supported | ✅ Yes (see insert/ remove rows for time complexity) |
Installation
pip install indexedheap
Feedback
If there is demand, I am considering adding support for heappushpop and heapreplace operations, similar to those in Python's heapq module.
Open to any feedback!
Updates
-
Updated terminology in the comparison table to show both "value" and "item" in some rows. Since the terminology used in my package for the inserted object is "value", whereas the terminology used in heapq is "item".
You can use Queue.PriorityQueue.
Recall that Python isn't strongly typed, so you can save anything you like: just make a tuple of (priority, thing) and you're set.
When using a priority queue, decrease-key is a must-have operation for many algorithms (Dijkstra's Algorithm, A*, OPTICS), I wonder why Python's built-in priority queue does not support it. None of the other answers supply a solution that supports this functionality.
A priority queue which also supports decrease-key operation is this implementation by Daniel Stutzbach worked perfectly for me with Python 3.5.
from heapdict import heapdict
hd = heapdict()
hd["two"] = 2
hd["one"] = 1
obj = hd.popitem()
print("object:",obj[0])
print("priority:",obj[1])
# object: one
# priority: 1