Heap 堆
Heap 堆是 Priority Queue 的一种。Max Heap的parent节点是子树最大的,root是最大值。 Min Heap的parent节点是子树最小的,root是最小值。左右child没有顺序。
定义父类:
public abstract class Heap<T extends Comparable<T>> implements Iterable<T> {
/**
* Max Heap
*/
public static boolean MAXHEAP = true;
/**
* Min Heap
*/
public static boolean MINHEAP = false;
protected boolean order;
protected Comparator<T> comparator;
/**
* Add item to heap
*
* @param item
* Item to be added
* @return true
*/
public abstract boolean add(T item);
/**
* Get and remove the top in the heap
*
* @return Top item in the heap
*/
public abstract T poll();
/**
* Get the top in the heap
*
* @return Top item in the heap
*/
public abstract T peek();
/**
* Remove the first occurrence of item
*
* @param item
* Item to be removed
* @return True if item is removed. False if item doesn't exist.
*/
public abstract boolean remove(T item);
/**
* Check if item exists in the heap.
*
* @param item
* Item to be checked.
* @return True if item exists. False otherwise.
*/
public abstract boolean contains(T item);
/**
* Check if the heap is empty.
*
* @return True if empty. False otherwise.
*/
public abstract boolean isEmpty();
/**
* Return the size of the heap.
*
* @return Size of the heap.
*/
public abstract int size();
/**
* Percolate Up
*
* @param k
* Index
*/
protected abstract void percolateUp(int k);
/**
* Percolate Down
*
* @param k
* Index
*/
protected abstract void percolateDown(int k);
/**
* Compare two items. Use natural order if comparator is not specified.
*
* @param a
* Item to be compared
* @param b
* Item to be compared
* @return In max heap, check a < b. In min heap, check a > b.
*/
protected boolean compare(T a, T b) {
if (comparator != null) {
int cmp = comparator.compare(a, b);
if (order == MAXHEAP) {
return cmp < 0;
} else {
return cmp > 0;
}
} else {
if (order == MAXHEAP) {
return a.compareTo(b) < 0;
} else {
return a.compareTo(b) > 0;
}
}
}
/**
* Swap two items in the heap.
*
* @param i
* Index of item.
* @param j
* Index of item.
*/
protected abstract void swap(int i, int j);
}
注意:堆中的元素必须是Comparable的。
数组实现:
public class ArrayHeap<T extends Comparable<T>> extends Heap<T> {
private T[] heap;
private int tail = -1;
/********* Constructors of Array Heap ********/
@SuppressWarnings("unchecked")
public ArrayHeap(int capacity, boolean order) {
heap = (T[]) new Comparable[capacity + 1];
this.order = order;
}
public ArrayHeap(int capacity, boolean order, Comparator<T> comparator) {
this(capacity, order);
this.comparator = comparator;
}
@SuppressWarnings("unchecked")
public ArrayHeap(boolean order) {
heap = (T[]) new Comparable[1 + 1];
this.order = order;
}
public ArrayHeap(boolean order, Comparator<T> comparator) {
this(order);
this.comparator = comparator;
}
public ArrayHeap(T[] array, boolean order) {
heap = array.clone();
tail = heap.length - 1;
this.order = order;
for (int k = heap.length / 2 - 1; k >= 0; k--) {
percolateDown(k);
}
}
public ArrayHeap(T[] array, boolean order, Comparator<T> comparator) {
heap = array.clone();
tail = heap.length - 1;
this.order = order;
this.comparator = comparator;
for (int k = heap.length / 2 - 1; k >= 0; k--) {
percolateDown(k);
}
}
/************* Heap Method *************/
@Override
public boolean isEmpty() {
return tail == -1;
}
@Override
public int size() {
return tail + 1;
}
@Override
public boolean add(T item) {
if (tail + 1 == heap.length) {
resize(heap.length << 1);
}
heap[++tail] = item;
percolateUp(tail);
return true;
}
@Override
public T poll() {
if (isEmpty()) {
return null;
}
T top = heap[0];
swap(0, tail);
heap[tail--] = null;
percolateDown(0);
if (tail + 1 == (heap.length >> 2)) {
resize(heap.length >> 1);
}
return top;
}
@Override
public T peek() {
return heap[0];
}
@Override
public boolean remove(T item) {
for (int i = 0; i <= tail; i++) {
if (heap[i].equals(item)) {
swap(i, tail);
heap[tail--] = null;
percolateUp(i);percolateDown(i);
return true;
}
}
return false;
}
@Override
public boolean contains(T item) {
for (int i = 0; i <= tail; i++) {
if (heap[i].equals(item)) {
return true;
}
}
return false;
}
@Override
protected void percolateUp(int k) {
while (k > 0 && compare(heap[(k - 1) >> 1], heap[k])) {
swap((k - 1) >> 1, k);
k = (k - 1) >> 1;
}
}
@Override
protected void percolateDown(int k) {
while ((k << 1) + 1 <= tail) {
int child = (k << 1) + 1; // left child
// Compare left child and right child
if (child + 1 <= tail && compare(heap[child], heap[child + 1])) {
++child; // right child
}
if (compare(heap[k], heap[child])) {
swap(k, child);
k = child;
} else {
break;
}
}
}
@Override
protected void swap(int i, int j) {
T temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}
private void resize(int capacity) {
T[] newheap = (T[]) new Comparable[capacity];
System.arraycopy(heap, 0, newheap, 0, tail + 1);
heap = newheap;
}
@Override
protected ArrayHeap<T> clone() {
ArrayHeap<T> temp = new ArrayHeap<T>(order);
temp.heap = heap.clone();
temp.tail = tail;
temp.comparator = comparator;
return temp;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (T i : heap) {
sb.append(i + " ");
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
ArrayHeap<T> temp = ArrayHeap.this.clone();
@Override
public boolean hasNext() {
return !temp.isEmpty();
}
@Override
public T next() {
return temp.poll();
}
};
}
}
注意:
1. percolateUp 和 percolateDown是核心操作。
2. 数组自动resize。
3. Iterate按poll的顺序。