您的位置:首页 > 其它

二叉堆

2016-05-20 15:55 239 查看
二叉堆是一种高级的数据结构,用来动态维护一个序列中的最值和对某一个数的删除或插入。堆满足下列性质:
1,堆是一棵完全二叉树。(因此可以用数组来表示且不浪费空间)        2,堆的每一个父亲节点的值均≥(大根堆)或≤(小根堆)其左右孩子的值。(下面若没有注明,均讨论大根堆)
下面来看一下堆的相关操作:【最值】 最值就不用说了吧,直接输出根节点就行了。因为根节点都大于等于其左右孩子,而它的左右孩子又大于等于其左右孩子……。【插入】 为了方便,插入时一般在数组的尾部,但插入后会出现一些不符合堆的性质的情况:h[ p ]>=h[ father(p) ],这是我们把它们交换,就可以维护性质了。但交换后还是可能出现违背性质的情况,所以,我们要从下往上进行交换。众所周知,father(p)=p/2,因此可以用p/2的步骤找到自己的父亲并进行交换。
void insert(int p)
{

h[++m]=p;
int j=m;
while((j>>1)>0 && h[j]>h[j>>1])
{
swap(h[j],h[j>>1]);
j>>=1;// j=j>>1; 相当于j=j/2;
}

return;
}

【删除】 假如我们要删除数组中第一个数,只要把第一个数和最后一个数进行交换就行了。这时,又会出现一些不符合堆的性质的情况出现:如H[p]<H[ left(p) ]或H[p]<H[ right(p) ]的情况出现。那么,我们把它们交换不就可以了!但是,我们还有一个问题,假如H[p]<H[ left(p) ]和H[p]<H[ right(p) ]的情况都出现,那么应该交换那个呢?应该是较大的那一个。为什么呢?

我们都知道,一个节点p的左孩子是p*2,右孩子是p*2+1,所以,我们可以从上往下进行比较并交换。
int Delete()//删除并输出最大值
{
int ans=h[1];
h[1]=h[m--];

int j=1,k;
while( j<<1<=m )
{
k=j<<1;
if(k<m && h[k]<h[k+1]) k++;//比较左孩子和右孩子的大小
if(h[k]<=h[j]) break;
swap(h[j],h[k]);//交换
j=k;
}
return ans;//最大值
}

以上就是一些关于堆的相关操作,时间效率都是O(logn)的。因此堆是一种非常有用的数据结构!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: