Lecture 13 - Problems

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();

}
  1. 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?

  2. 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?

  3. 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) {
        A = unsorted_array;
        size = 0;
      }
    
      /** 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.

  4. 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”.

    1. 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
      }
    2. 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
      }
    3. 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.