Priority Queues and Heaps
A collection of prioritized elements that allow arbitrary element insertion, and allows the removal of the elmenet that has first priority. Priority is provided by an associated key - and the element with the minimum key will be the next to be removed from the queue. The key must define a natural order i.e. a < b
for any instance a
and b
.
Priority Queue ADT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Implementation with Unsorted List
In this we store entries within an unsorted list using a doubly-linked list (PositionalList
) defined from
The doubly linked list ensures all of the operations execute in O(1)
time except for min
and _find_min
which would take O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
Implementation with a Sorted List
A alternative is to use a positional list but maintaining the entries sorted by non-decreasing keys. But in this case the insertion of a new entry has a cost of O(n)
using insertion sort.
But min
and remove_min
take oly O(1)
time now.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Heaps
A data structure that provides an efficient realization of a priority queue - both insertions and removals are in logarithmic time - which is a significant improvement over the list based implementations.
A binary heap uses a binary tree which helps find a compromise between elements being entirely unsorted and perfectly sorted.
In python this is implemented as a heapq
.
Properties
- Stores a collection of items at its positions
- Heap Order Property - for every position
p
other than the root, the key stored atp
is greater than or equal to the key stored atp's
parent- Point 2. means that the minimum key is always stored at the root of the heap. Keys encountered on a path from the root to the leaf of a heap are in nondecreasing order.
- Complete Binary Tree Property - a heap with height
h
is complete - Height of a Heap - given that it is complete,
height h = floor(log n)
Array based representation
The array-based representation of the complete binary tree are based on the properties:
- If
p
is the root ofT
thenf(p) = 0
- If
p
is the left child of positionq
, thenf(p) = 2f(q) + 1
- If
p
is the right child of positionq
, thenf(p) = 2f(q) + 2
With this implementation, the last position of the heap is always at index n-1
, where n is the number of positions of T
. This reduces the complexities of a node-based tree structure and heap operations (e.g. locating the last position of a complete binary tree).
Implementation
Operations on a heap need to maintain its complete binary tree properties.
Key operations of a heap:
- add(k,v) - adding a key, value pair at position
p
just beyond the right most node, and thenup-heap bubbling
to maintain heap-order property - remove_min() - remove and return (k,v) tuple with minimum keyalong with
down-heap bubbling
after removal.
Up-Heap Bubbling
Once a new (k,v)
pair has been added to the rightmost node at the bottom level (or new level) of the tree, a comparison of the key at position p
to that of the parent of p
is done until heap-order property is satisfied.
Worst case scenario, a new entry moves all the way to the root of the heap with a bound of floor(log(n))
.
Down-Heap Bubbling
When the minimumn is removed as a root of the tree, the leaf at the last position of the tree is copied to the root, and the node at the last position is deleted.
If the heap has more than one node (the root) then we identify two cases where p
initially denotes the root of the tree T
:
- if
p
has no right child, letc
be the left child ofp
- other (
p
has both children) then letc
be a child ofp
with minimal key
Until \(k_p > k_c\) swap the entries stored at p
and c
until the heap-order property is satisfied for both p
and all of c
. This means that even though the heap-order property may be locally restored for node p
relative to its children, there may be a violation of this property at c
, hence we have to continue swapping down T
until no violation of the heap-order property occurs.
Python Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
|
Applications
Sorting
- Selction Sort
- Insertion Sort
- Heap Sort
Adaptable Priority Queues
Adaptable priority queues extends the base implementation to additional methods:
- remove(loc) ability to remove any node (not just the min) from the heap
- update(loc, k, v) ability to modify the priority of an existing node
To support this we will implement a locator - similar to Position
but with one major difference - locator does not represent a tangible placement of an element within the structure.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
|
References
-
Skiena, Steven S.. (2008). The Algorithm Design Manual, 2nd ed. (2). : Springer Publishing Company. ↩
-
Goodrich, M. T., Tamassia, R., & Goldwasser, M. H. (2013). Data Structures and Algorithms in Python (1st ed.). Wiley Publishing. ↩
-
Cormen, T. H., Leiserson, C. E., & Rivest, R. L. (1990). Introduction to algorithms. Cambridge, Mass. : New York, MIT Press. ↩