OPERATION | DESCRIPTION |
PriorityQ() | (constructor) create an empty priority queue |
boolean empty() | return true iff the priority queue is empty |
void insert(Comparable p) | add priority p to the priority queue |
Comparable removeMax() | remove and return the highest priority from the priority queue (error if the priority queue is empty) |
A priority queue can be implemented using many of the data structures that we've already studied (an array, a linked list, or a binary search tree). However, those data structures do not provide the most efficient operations. To make all of the operations very efficient, we'll use a new data structure called a heap.
Consider implementing a priority queue using an array, a linked list, or a BST. For each, describe how each of the priority queue operations would be implemented, and what the worst-case time would be.
A heap is a binary tree (in which each node contains a Comparable
key value), with two special properties:
The ORDER property:
The SHAPE property:
And here are some more trees;
they all have the shape property, but some violate the order property:
Now let's consider how to implement priority queues using a heap.
The standard approach is to use an array (or an ArrayList),
starting at position 1 (instead of 0),
where each item in the array corresponds to one node in the heap:
Note that the heap's "shape" property guarantees that there are never
any "holes" in the array.
The operations that create an empty heap and return the size of the
heap are quite straightforward; below we discuss the
insert and removeMax operations.
When a new value is inserted into a priority queue, we need to:
Insert the values 6, 40, and 28 into the tree shown above (after 34
has been inserted).
Because heaps have the order property, the largest
value is always at the root.
Therefore, the removeMax operation will always remove and
return the root value;
the question then is how to replace the root node so that the heap
still has the order and shape properties.
The answer is to use the following algorithm:
Perform 3 more removeMax operations using the example tree.
For the insert operation, we start by adding a value to the end
of the array (constant time, assuming the array doesn't have to be
expanded);
then we swap values up the tree until the order property has been restored.
In the worst case, we follow a path all the way from a leaf to the root
(i.e., the work we do is proportional to the height of the tree).
Because a heap is a balanced binary tree, the height of the
tree is O(log N), where N is the number of values stored in the tree.
The removeMax operation is similar: in the worst case, we follow a
path down the tree from the root to a leaf.
Again, the worst-case time is O(log N).
Heaps
For every node n, the value in n is greater than or equal to
the values in its children (and thus is also greater than or equal
to all of the values in its subtrees).
Here are some binary trees, some of which violate the shape properties,
and some of which respect those properties:
Implementing priority queues using heaps
Here's an example, showing both the conceptual heap (the binary tree),
and its array representation:
Implementing insert
The way to achieve these goals is as follows:
Here's a series of pictures to illustrate inserting the value 34
into a heap:
Implementing removeMax
Here's a series of pictures to illustrate the removeMax operation
applied to the heap shown above.
Complexity