Implementing ArrayHeap

The questions in this section use this outline of ArrayHeap, a binary heap stored in an array in level order. It implements PriorityQueue<T>: add throws IllegalArgumentException if the item is null, and remove deletes the highest-priority element and throws NoSuchElementException if the heap is empty. The helpers below are already written.

public class ArrayHeap<T extends Comparable<T>> implements PriorityQueue<T> {
  private T[] heap;                  // the complete tree in level order, root at heap[0];
                                     // the constructors allocate it with length 10
  private int size;                  // heap[0] through heap[size - 1] are filled
  private Comparator<T> comparator;  // null means use natural ordering

  // Returns a negative number if a has higher priority than b, zero if they
  // tie, and a positive number if a has lower priority.
  private int compare(T a, T b) { ... }

  // The parent of the node at index i. Pre: i > 0.
  private int parent(int i) { ... }

  // The left child of the node at index i.
  private int leftChild(int i) { ... }

  // The right child of the node at index i.
  private int rightChild(int i) { ... }

  // Exchanges the elements at indices i and j.
  private void swap(int i, int j) { ... }

  // Replaces heap with an array of twice the length, holding the same elements.
  private void grow() { ... }
}
Solution
private void swim(int i) {
  while (i > 0 && compare(heap[i], heap[parent(i)]) < 0) {
    swap(i, parent(i));
    i = parent(i);
  }
}
Solution
private void sink(int i) {
  while (leftChild(i) < size) {
    int best = leftChild(i);
    int right = rightChild(i);
    if (right < size && compare(heap[right], heap[best]) < 0) {
      best = right;
    }
    if (compare(heap[best], heap[i]) >= 0) {
      break;
    }
    swap(i, best);
    i = best;
  }
}
Solution
@Override
public void add(T item) {
  if (item == null) {
    throw new IllegalArgumentException();
  }
  if (size == heap.length) {
    grow();
  }
  heap[size] = item;
  size++;
  swim(size - 1);
}
Solution
@Override
public void remove() {
  if (size == 0) {
    throw new NoSuchElementException();
  }
  heap[0] = heap[size - 1];
  heap[size - 1] = null;
  size--;
  if (size > 0) {
    sink(0);
  }
}
Solution

In the linked heap, a node has no reference to its parent. The recursion is what remembers the path back up: each call waiting on the call stack holds one node on that path. In the array, parent(i) computes the parent’s index, so nothing has to remember the path, and i = parent(i) moves up one level.