//若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:
//树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
//注意:是从坐标1开始的
//假设完全二叉树的某一个节点i,它的左子树,右子树已经是堆,接下来需要将r[2i].key与r[2i+1].key之中的最大者与
//r[i].key比较,若r[i].key较小则将其与最大孩子的关键字交换,这有可能破坏下一级的堆,于是继续采用上述方法构造下一级的
//堆,知道完全二叉树中的节点i构成堆为止。对于任意一颗完全二叉树,i取[n/2]~1,反复利用上述方法建堆。大者“上浮”,小者“下沉”。
#include <iostream>
using namespace std;
#define Type int
void sift(Type r[],int low,int high)
{
int i=low,j=2*i;
Type tmp=r[i];
while(j<=high)
{
if (j<high && r[j] < r[j+1])
++j;///////////找到较大的孩子
if (tmp < r[j])//若较大的孩子大于父节点的,就交换,交换了就得处理下一级堆
{
r[i]=r[j];
i=j;
j=2*i;
}
else break;//没交换,不用交换不用处理下一级堆
}
r[i]=tmp;
}
void heapsort(Type r[],int n)
{
int i;
Type tmp;
for ( i = n/2; i >= 1; --i)//循环建立初始堆
sift(r,i,n);
for ( i = n; i >= 2; --i)
{
tmp=r[1];
r[1]=r[i];
r[i]=tmp;
sift(r,1,i-1);//每一趟排序的基本操作:将当前无序区的堆顶记录R[1]
//和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
}
}
int main(int argc, char const *argv[])
{
Type r[9]={0,51,54,55,15,15,1,787,5};
heapsort(r,8);
for (int i = 1; i < 9; ++i)
{
cout<<r[i]<<" ";
}
return 0;
}
原文:http://blog.csdn.net/h1023417614/article/details/20847331