一、堆的定义
堆结构是一种数组对象,它可以被视为一棵完全二叉树,如下图:
二、堆的性质
设数组A的长度为len,二叉树的结点个数为size,size≤len,则A[i]存储二叉树中编号为i的结点值(1≤i≤size),而A[size]以后的元素并不属于相应的堆,树的根为A[1],并且利用完全二叉树的性质,我们很容易求第i个结点的父结点、左孩子结点、右孩子结点的下标了,分别为:i/2、2i、2i+1;
堆具有这样一个性质:即除根结点以外,所有结点的值都不得超过其父结点的值,这样就推出,堆中的最大元素存放在根结点中,且每一结点的子树中的结点值都小于等于该结点的值,这种堆又称为“大根堆”;反之,对除根以外的每个结点i,A[parent(i)]≤A[i]的堆,称为“小根堆”。
三、堆的操作
1、往堆中加入一个元素的算法如下:
(1)在堆尾加入一个元素,并把这个结点置为当前结点。
(2)比较当前结点和它父结点的大小, 如果当前结点小于父结点,则交换它们的值,并把父结点置为当前结点。转(2)。如果当前结点大于等于父结点,则转(3)。
(3)结束。
void put(int d)//小根堆,heap[1]为堆顶,元素最小
{
int now,next;
heap[++heap_size]=d;//在堆尾加入一个元素
now=heap_size;
while(now>1)
{
next=now>>1;//next=now/2;next相当于now的父亲节点
if(heap[now]>heap[next]) break;//如果为大根堆,heap[now]<heap[next]
swap(heap[now],heap[next]);
now=next;
}
}
2、从堆中取出并删除一个元素的算法如下:
(1)取出堆的根结点的值。
(2)把堆的最后一个结点(len)放到根的位置上,把根覆盖掉。把堆的长度减一。
(3)把根结点置为当前父结点pa。
(4)如果pa无儿子(pa>len/2),则转(6);否则,把pa的两(或一) 个儿子中值最小的那个置为当前的子结点son。
(5)比较pa与son的值,如果fa的值小于或等于son,则转(6);否则,交换这两个结点的值