/** A min-heap. */
class Heap<E extends Comparable<E>> {
//traditionally use E[] and size variable, but...
private ArrayList<E> array = new ArrayList<E>();
/** Constructs an empty heap. */
public Heap() {
}
public void add(E item) {
array.add(item); //add to end
heapifyUp(array);
}
/**
* Adjusts position of last element as necessary.
* Assumes the rest of the array is already a valid heap.
*/
private void heapifyUp(ArrayList<E> array) {
int i = array.size() - 1; //last element
int parent = (i - 1) / 2;
while (i > 0 && array.get(i).compareTo(array.get(parent)) < 0) {
//item is smaller than parent so needs to move up
Collections.swap(array, i, parent);
i = parent;
parent = (i - 1) / 2;
}
}
}
public E remove() {
if (array.size() == 0) {
throw new IllegalStateException("Heap is empty.");
}
E root = array.get(0);
array.set(0, array.remove(array.size() - 1));
heapifyDown(array);
return root;
}
/**
* Adjust position of first element as necessary.
* Assumes that the rest of array is already heapified.
* That is, elements at index 1 and 2 are roots of valid heaps.
*/
private void heapifyDown(ArrayList<E> array) {
int i = 0;
while (i < array.size()) { //or while(true)
int indexOfMin = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < array.size() &&
array.get(left).compareTo(array.get(indexOfMin)) < 0) {
indexOfMin = left;
}
if (right < array.size() &&
array.get(right).compareTo(array.get(indexOfMin)) < 0) {
indexOfMin = right;
}
if (i == indexOfMin) {
break;
}else {
Collections.swap(array, i, indexOfMin);
i = indexOfMin;
}
}
}
For more complex heap implementations:
public static <E extends Comparable<E>> void heapSort(E[] array) {
//heapify from bottom up, skipping all leaves, which are already heaps of size 1
for (int i = array.length / 2; i >= 0; i--) {
heapify(array, i, array.length);
}
// grab max element from heap and swap to end of array
for (int i = array.length - 1; i > 0; i--) {
//swap root to end of array
E temp = array[0];
array[0] = array[i];
array[i] = temp;
heapify(array, 0, i);
}
}
/**
* Produces a max-heap rooted at the given root index and containing a number
* total elements equal to length. Assumes that the children at
* (2 * root + 1) and (2 * root + 2) are the roots of valid heaps.
*/
private static <E extends Comparable<E>> void heapify(E[] array, int root, int length) {
//basically heapifyDown method for an array
int i = root;
while (true) {
int indexOfMax = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < length &&
array[left].compareTo(array[indexOfMax]) > 0) {
indexOfMax = left;
}
if (right < length &&
array[right].compareTo(array[indexOfMax]) > 0) {
indexOfMax = right;
}
if (i == indexOfMax) {
break;
}else {
//swap
E temp = array[i];
array[i] = array[indexOfMax];
array[indexOfMax] = temp;
i = indexOfMax;
}
}
}