二叉堆
- 完全二叉树
- 高为h的完全二叉树有 2^h~2^(h+1)-1个节点,高为O(log N)
- insert——插入通过上滤实现,最好为O(1),最坏情况为O(log N),一次插入平均需要2.607次比较,因此平均一次插入上移1.607层
- deleteMin——删除最小元通过下滤实现,,最坏情况为O(log N),平均时间为O(log N)
- decreaseKey——降低关键字的值,需要上滤改变堆的结构,提升了优先级
- increaseKey——增加关键字的值,需要下滤改变堆的结构,降低优先级
- delete——删除操作可以先decreaseKey,再deleteMin
- buildHeap——通过N个insert来完成,总的平均时间为O(N)
- buildHeap——一般是通过先构成数组,再经过N/2次的下滤构造
public class BinaryHeap<T extends Comparable<? super T>> {
private static final int DEFAULT_CAPACITY = 10;
private int mCurrentSize;
private T[] mItems;
public BinaryHeap() {
}
public BinaryHeap(int capacity) {
}
public BinaryHeap(T[] items) {
mCurrentSize = items.length;
mItems = (T[]) new Comparable[(mCurrentSize + 2) * 11 / 10];
int i = 1;
for (T item : items) {
mItems[i++] = item;
}
buildHeap();
}
public void insert(T t) {
if (mCurrentSize == mItems.length - 1) {
enlargeArray(mItems.length * 2 + 1);
}
int hole = ++mCurrentSize;
for (; hole > 1 && t.compareTo(mItems[hole / 2]) < 0; hole = hole / 2) {
mItems[hole] = mItems[hole / 2];
}
mItems[hole] = t;
}
public T findMin() {
return mItems[1];
}
public T delteMin() {
if (isEmpty()) {
throw new NullPointerException();
}
T min = findMin();
mItems[1] = mItems[mCurrentSize--];
percolateDown(1);
return min;
}
public boolean isEmpty() {
return mCurrentSize <= 0;
}
public void makeEmpty() {
mCurrentSize = 0;
mItems = (T[]) new Comparable[DEFAULT_CAPACITY + 1];
}
private void percolateDown(int hole) {
int child;
T tmp = mItems[hole];
for (; hole * 2 <= mCurrentSize; hole = child) {
child = hole * 2;
if (child != mCurrentSize && mItems[child + 1].compareTo(mItems[child]) < 0) {
child++;
}
if (mItems[child].compareTo(tmp) < 0) {
mItems[hole] = mItems[child];
} else {
break;
}
}
mItems[hole] = tmp;
}
private void buildHeap() {
for (int i = mCurrentSize / 2; i > 0; i--) {
percolateDown(i);
}
}
private void enlargeArray(int newSize) {
T[] array = (T[]) new Comparable[newSize];
System.arraycopy(mItems, 0, array, 0, 1 + mCurrentSize);
mItems = array;
mCurrentSize = newSize;
}
}
应用:
- N个元素找出第k个最小的元素。
- 将N个元素读入数组,使用buildHeap算法,然后执行k次deleteMin操作,即可得到答案。
- 复杂度 O(N)+k*O(log N)