Trees and Priority Queues (Heaps)
This will be our first introduction to Trees. Over the next few weeks, we will discuss several different kinds of trees.
We'll start with a heap, also known as a priority queue. What distinguishes a priority queue from a regular queue is that items are assigned and ordered by priority. This could be implemented easily enough using either an array or a linked list, and simply insert each new item in the appropriate spot. The next available item would be at the top of the queue.
Instead, we are going to implement this with a variant of a binary tree.
A heap as a binary tree has the following characteristics:
1. It is complete, meaning that each row (except perhaps the last) is filled
2. Each node satisfies the heap condition, which states that a node's key is greater than or equal to both of its children
3. It is weakly ordered, meaning that there is no easy way to search the tree for a specific value
Inserting into a heap uses a process known as trickle-up. The process works as follows:
1. Insert the new node in the first available position in the heap, which is always in the last row.
2. Compare the new node with its parent. If the new node is larger, then swap the new node with its current parent (trickle up)
3. Repeat step #2 until the new node is smaller than or equal to its parent
Removing from a heap uses a process know as trickle-down. The process works as follows:
1. Swap the last node with the first node.
2. Remove the last node (which now contains the value of from the first node)
3. Compare the node with each of its children. Swap it with whichever child is larger.
4. Repeat step #3 until both of its children are smaller.
Heaps are often implemented as an array. In order to do this successfully, there are a few variables to calculate and track. Note that all calculation should use integer division, which is the forward slash.
current size- this will also assist in finding the position in which to insert new nodes
parent- for a node at position x in the array, its parent is located at position (x-1)/2
left child- for a node at position x in the array, its left child is located at 2*x+1, or the right child minus 1
right child- for a node at position x in the array, its right child is located at 2*x+2, or the left child plus 1
Inserting into a heap array takes the following steps:
bool insertNode(int i) {
if ( current size != array size ) {
store i in the next available position in the array
trickle up i
increment the array size
return true;
}
return false;
}
void trickleUp(int index) {
calculate parent position
store the value at index in a temp variable
while (index > 0 && value of parent < temp variable ) {
swap the value at index with the value at parent
set index equal to parent
calculate new parent position
}
store the value in the temp variable at the current index position
}
Removing from a heap array takes the following steps:
int deleteNode() {
if ( current size != 0 ) {
store the value at the top of the heap in a temp variable
decrement the current size
place the value at current size into the first position
trickle down the value in the first position
return the temp variable
}
return NULL;
}
void trickleDown(int index) {
store the value in the first position in a temp variable
while ( index < half the current size ) {
calculate the position of the left child
calculate the position of the right child
if (
right child < current size &&
value stored in left child is less than value stored in right child
) larger child is the right child
else larger child is the left child
if ( value in the temp variable >= value at the larger child position )
exit the while loop, we're finished
store the value at the larger child position into the index position
set the index to the larger child
}
}