Heaps and Priority Queues: Computer Science E-119 Harvard Extension School Fall 2012 David G. Sullivan, PH.D
Heaps and Priority Queues: Computer Science E-119 Harvard Extension School Fall 2012 David G. Sullivan, PH.D
Heaps and Priority Queues: Computer Science E-119 Harvard Extension School Fall 2012 David G. Sullivan, PH.D
3 2 3 1 2 3 1 2 3 1 2
4 1 5 4 7 5 4 5 4 5 its successors
6 7 8 6 8 6 7 8 6 7 8
• Examples:
26 10 8 17 14 3
12 32
10
4 18 28
8 17
26 12 32 4 18 28 14 3
a[7] a[8]
• Examples:
• the left child of the node in a[1] is in a[2*1 + 1] = a[3]
• the right child of the node in a[3] is in a[2*3 + 2] = a[8]
• the parent of the node in a[4] is in a[(4 – 1)/2] = a[1]
• the parent of the node in a[7] is in a[(7 – 1)/2] = a[3]
Heaps
• Heap: a complete binary tree in which each interior node is
greater than or equal to its children
• Examples:
28 18 12
16 20 8 2 7 10
12 8 5 3 7
sift down 5 20 20
the 5:
20 12 5 12 16 12
16 8 16 8 5 8
7 18 7 10
3 5 8 6 3 5 8 6
sift down
7 26 26
the 7:
26 23 7 23 18 23
15 18 10 15 18 10 15 7 10
siftDown() Method
private void siftDown(int i) {
HeapItem toSift = contents[i];
int parent = i;
int child = 2 * parent + 1;
while (child < numItems) {
// If the right child is bigger, compare with it.
if (child < numItems - 1 &&
contents[child].compareTo(contents[child + 1]) < 0)
child = child + 1;
if (toSift.compareTo(contents[child]) >= 0)
break; // we’re done
// Move child up and move down one level in the tree.
contents[parent] = contents[child];
parent = child;
child = 2 * parent + 1;
} 26 toSift: 7
contents[parent] = toSift;
parent child
} 18 23 0 1
1 3
• We don’t actually swap
1 4
items. We wait until the 15 7 10
4 9
end to put the sifted item 0 1 2 3 4 5
in place. 26 18 23 15 7 10
remove() Method
public HeapItem remove() {
HeapItem toRemove = contents[0];
return toRemove;
}
28 5 20
20 12 20 12 16 12
16 8 5 16 8 5 8
0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
28 20 12 16 8 5 5 20 12 16 8 5 20 16 12 5 8 5
5 8 5 8 35
20 20 35
sift it up:
16 12 16 35 16 20
5 8 35 5 8 12 5 8 12
insert() Method
public void insert(HeapItem item) {
if (numItems == contents.length) {
// code to grow the array goes here…
}
contents[numItems] = item;
siftUp(numItems);
numItems++;
}
20 20 35
16 12 16 12 16 20
5 8 5 8 35 5 8 12
0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
20 16 12 5 8 20 16 12 5 8 35 35 16 20 5 8 12
14 20 1 26
• Last element’s parent = contents[(7 – 2)/2] = contents[2].
Sift it down:
5 5
16 8 16 26
14 20 1 26 14 20 1 8
16 26 20 26
14 20 1 8 14 16 1 8
20 26 20 5 20 8
14 16 1 8 14 16 1 8 14 16 1 5
Creating a Heap from an Array
public class Heap {
private HeapItem[] contents;
private int numItems;
...
public Heap(HeapItem[] arr) {
// Note that we don't copy the array!
contents = arr;
numItems = arr.length;
makeHeap();
}
private void makeHeap() {
int last = contents.length - 1;
int parentOfLast = (last - 1)/2;
for (int i = parentOfLast; i >= 0; i--)
siftDown(i);
}
...
}
16 8
14 20 1 26
Heapsort (~cscie119/examples/heaps/HeapSort.java)
public class HeapSort {
public static void heapSort(HeapItem[] arr) {
// Turn the array into a max-at-top heap.
// The heap object will hold a reference to the
// original array, with the elements rearranged.
Heap heap = new Heap(arr);
int endUnsorted = arr.length - 1;
while (endUnsorted > 0) {
// Get the largest remaining element and put it
// where it belongs -- at the end of the portion
// of the array that is still unsorted.
HeapItem largestRemaining = heap.remove();
arr[endUnsorted] = largestRemaining;
endUnsorted--;
}
}
}
6
... ...
heap
arr
28 16 20 12 8 5
Heapsort Example
0 1 2 3 4 5 6
• Sort the following array: 13 6 45 10 3 22 5
6 45
10 3 22 5
10 3 22 5 6 3 22 5 6 3 13 5
no change, because
45 >= its children
6 3 13 5
6 3 13 5 6 3 5 6 3 5
0 1 2 3 4 5 6 0 1 2 3 4 5 6
toRemove: 45 22 10 13 6 3 5 5 22 10 13 6 3 5 45
endUnsorted: 6 endUnsorted: 5
largestRemaining: 45
Heapsort Example (cont.)
copy 22; 5
22 13 13
move 5 sift down 5; put 22
to root return 22 in place
10 13 10 5 10 5
6 3 5 6 3 6 3
0 1 2 3 4 5 6 0 1 2 3 4 5 6
toRemove: 22 13 10 5 6 3 5 45 13 10 5 6 3 22 45
endUnsorted: 5 endUnsorted: 4
largestRemaining: 22
copy 13; 3
13 10 10
move 3 sift down 3; put 13
to root return 13 in place
10 5 6 5 6 5
6 3 3 3
0 1 2 3 4 5 6 0 1 2 3 4 5 6
toRemove: 13 10 6 53 3 22 45 10 6 5
3 13 22 45
endUnsorted: 4 endUnsorted: 3
largestRemaining: 13
3
0 1 2 3 4 5 6 0 1 2 3 4 5 6
toRemove: 10 6 3 53 13 22 45 6 3
5 10 13 22 45
endUnsorted: 3 endUnsorted: 2
largestRemaining: 10
copy 6; 65 5 5
move 5 sift down 5; put 6
to root return 6 in place
3 5 3 3
0 1 2 3 4 5 6 0 1 2 3 4 5 6
toRemove: 6 5 3 5 10 13 22 45 5 3
6 10 13 22 45
endUnsorted: 2 endUnsorted: 1
largestRemaining: 6
Heapsort Example (cont.)
copy 5; 3
5 3 3
move 3 sift down 3; put 5
to root return 5 in place
3
0 1 2 3 4 5 6 0 1 2 3 4 5 6
toRemove: 5 3 3 6 10 13 22 45 3 5
6 10 13 22 45
endUnsorted: 1 endUnsorted: 0
largestRemaining: 5
3 2 3 1 2 3 1 2 3 1 2
4 1 5 4 7 5 4 5 4 5 its successors
6 7 8 6 8 6 7 8 6 7 8
h=3 h=3 h=1 h=3
heuristic values and
p = -3 p = -3 p = -1 p = -3 priorities
• Greedy search would consider the highlighted successor before
the other successors, because it has the highest priority.
• Greedy search is:
• incomplete: it may not find a solution
• it could end up going down an infinite path
• not optimal: the solution it finds may not have the lowest cost
• it fails to consider the cost of getting to the current state
A* Search
• Priority of state x, p(x) = -1 * (h(x) + g(x))
where g(x) = the cost of getting from the initial state to x
3 1 2
4 5
6 7 8
3 2 3 1 2 3 1 2 3 1 2
4 1 5 4 7 5 4 5 4 5
6 7 8 6 8 6 7 8 6 7 8
h=3 h=3 h=1 h=3
p = -(3 + 1) p = -(3 + 1) p = -(1 + 1) p = -(3 + 1)
3 2 3 2
4 1 5 4 1 5
6 7 8 6 7 8
h=4 h=4
p = -(4 + 2) p = -(4 + 2)
• For example:
public class GreedySearcher extends Searcher {
private Heap nodePQueue;