堆有两个性质:结构性和堆序性
堆是一棵完全二叉树。一棵高为h的完全二叉树有2^h到(2^h+1)-1节点。这意味着完全二叉树的高是⌊logN⌋,显然它是O(log N)。因为它这么有规律,它可以用一个数组表示而不需要使用链。
一个堆结构将由一个Comparable对象的数组和一个代表当前堆的大小的整数组成。
堆序性质(最小堆):在一个堆中,对于每个节点X,X的父亲中的关键字小于或等于X中的关键字,根节点除外(它没有父亲)。
基本操作:
//插入操作
public void insert(AnyType x){
if(currentSize == array.length - 1)
enlargeArray(2 * array.length + 1);
//上滤
int hole = ++currentSize;
for(array[0] = x; x.compareTo(array[hole/2]) < 0; hole/=2)
array[hole] =array[hole/2];
array[hole]= x;
}
//删除最小值操作
public AnyType deleteMin() throws Exception{
if(isEmpty()) throw new Exception( );
AnyType min = findMin();
array[1]= array[currentSize--];
percolateDown(1);
return min;
}
//下滤操作
public void percolateDown(int hole ){
AnyType tmp = array[hole];
int child;
for(; hole*2 <= currentSize; hole = child){
child = hole * 2;
if(child != currentSize -1 && array[child +1].compareTo(array[child]) < 0)
child++;
if(array[child].compareTo(tmp) < 0)
array[hole] = array[child];
else
break;
}
array[hole] = tmp;
}
//建堆操作
public void buildHeap(){
for(int i = currentSize/2; i > 0; i--)
percolateDown(i); //对所有中间节点进行下滤操作
}
其他堆操作
虽然求最小值操作可以在常数时间完成,但是,最小堆在求最大元方面没有任何帮助。事实上,一个堆蕴含的序信息很少,若不对整个堆进行线性搜索,没有办法找到特定的关键字。
下述前三个操作均以对数最坏情形时间运行。
(1)decreaseKey(降低关键字的值)
decreaseKey(p,∆)操作降低在位置p处的项的值,降值的幅度为正的量∆。由于可能破坏堆序性,因此必须上滤调整。该操作对系统管理员有用,能使他们的程序以最高的优先级运行。
(2)increaseKey(增加关键字的值)
可能需要下滤操作。许多调度程序员自动降低正在过多消耗CPU时间的进程的优先级。
(3)delete(删除)
delete(p)操作删除堆中位置p的节点。该操作可以通过执行decreaseKey(p,∞)然后执行deleteMin()来完成。当一个进程被用户终止而不是正常终止时,它必须从优先队列中除去。