Here is the same barebones Heap
class we’ve seen
already, with method specs and headers but no implementation.
public class Heap {
int[] A;
int size;
/** Add the value v to the heap. */
public void add(int v);
/** Return the smallest value in the heap without modifying the heap.
* Precondition: size >= 1 */
public int peek();
/** Remove and return the minimum value in the heap.
* Precondition: size >= 1 */
public int poll();
}
The kind of heap we’ve been talking about are formally called “min-heaps”, because the minimum value is always at the root. It is also possible to create a “max-heap”, where the maximum value is at the root. How do we need to change the definition (properties) of a heap to switch it from a min-heap to a max-heap?
There is a sorting algorithm called HeapSort. How do you think
this might work? Write some pseudocode for a method
heapSort(int[] a)
that uses a Heap
like the
one above to sort an array of integers. What is the runtime of your
algorithm? Is it in-place? Stable?
It turns out to be possible to write an in-place version of
HeapSort
using a max-heap. To get you started, here’s a
max-heap version of the Heap
class above with a couple
extra methods added. The first is a constructor that takes an array of
unsorted values and sets that to be the Heap’s internal storage
array:
public class Heap {
int[] A;
int size;
/** Constructor: initialize a heap with an unsorted array of values
* as the backing storage. Although A has values, size is 0 so the
* heap starts out empty. */
public Heap(int[] unsorted_array) {
= unsorted_array;
A = 0;
size }
/** Add the value v to the heap. */
public void add(int v);
/** Return the largest value in the heap without modifying the heap.
* Precondition: size >= 1 */
public int peek();
/** Remove and return the largest value in the heap.
* Precondition: size >= 1 */
public int poll();
/** Sort the values in A in-place using heapsort.
* Precondition: the heap is empty and A contains all values to be sorted.
* Postcondition: the heap is empty and A's values are in sorted order. */
public void heapSort() {
// your code here
}
}
The second method is the heapSort()
method, which sorts
the values in A
in-place. Implement the
heapSort
method.
The most straightforward way to insert \(n\) elements into a heap is to call
add
\(n\) times, which is
\(O(n \log n)\). However, it turns out
to be possible to build a heap of \(n\)
relements in \(O(n\)) time. There are
two tricky parts to this: the algorithm to build the heap, and the
analysis to show that it’s \(O(n)\). In
short, the approach is to build the heap “bottom-up” instead of
“top-down”.
Write pseudocode to implement the following method, which could
be a member of the Heap
class above:
/** Swap i down to its appropriate position in the bottom-up collection
* of heaps thus far constructed.
* Preconditions:
* - i's left subtree is nonempty
* - i's left subtree and right subtree (if it exists) are max-heaps
* Postcondition: the subtree rooted at i is a max-heap
*/
private void maxHeapify(int i) {
// your code here
}
Noticing that a single value is always a valid heap, write
pseudocode for the following, making use of the maxHeapify
method above:
/** Build a max heap from from the contents of A.
* Postcondition: A[0] is the root of a max-heap */
public void maxHeapify() {
// your code here
}
For a given call to maxHeapify(i)
, the runtime is
\(O(\log n)\) where \(n\) is the number of nodes in the tree
rooted at i
. Although maxHeapify()
makes \(O(n)\) calls to the private helper, it’s
possible to show that it only does a total of \(O(n)\) work. Prove this. Hint: the
analysis is similar to the analysis of the recursive height
calculation in AVL trees that we saw in Lecture 11 Problem 3.