这两天看了下堆排序, 意思是理解了,不过还没找到用处。。。

先练练打字吧。。

堆排序(Heap Sort)只需要一个记录大小的辅助空间,每个待排序的记录仅占有一个存储空间。

堆的定义如下:n个元素的序列{k1,k2,k3.....kn}当且仅当满足以下关系时,称之为堆。

Ki <= K(2*i)  && Ki <= K(2*i+1)       或者     Ki >= K(2*i)  && Ki >= K(2*i+1)        (i=1,2,...n/2)

若将此序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右

孩子的结点的值。由此,若序列{k1,k2,...kn}是堆,则堆顶元素(或完全二叉树的根)必须为序列中n个元素的最小值(或最大值)。

若在输出堆顶的最小值之后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素中的次小值。如此反复执行,便能得到一个有序序列,这个过程称之为堆排序。

      由此,实现堆排序需要解决两个问题:(1)如何由一个无序序列建成一个堆?(2)如何在输出堆顶元素之后,调整剩余元素成为一个新的堆?

(此处省略n个字,由于需要画图,此处不便写,见谅。。)

我们称自堆顶至叶子的调整过程为“筛选”。

从一个无序序列建堆的过程就是一个反复“筛选”的过程。若将此序列看成是一个完全二叉树,则最后一个非终端结点是第n/2个元素,由此“筛选”只需从第n/2

个元素开始。

贴上代码:

# include<stdio.h>
int a[1000005];
/*void HeapAdjust1(int s,int length)
{
	int rc,j;
	for(j=2*s;j<=length;j*=2)
	{
		if(j<length && a[j+1]>a[j]) j++;
		if(a[j]<=a[s]) break;
		rc=a[j];
		a[j]=a[s];
		a[s]=rc;
		s=j;
	}
}*/
void HeapAdjus2(int s,int length)
{
	int rc,j;
	rc=a[s];
	for(j=2*s;j<=length;j*=2)
	{
		if(j<length && a[j+1]>a[j]) j++;
		if(a[j]<=rc) break;
		a[s]=a[j];
		s=j;
	}
	a[s]=rc;
}
int main()
{
	int i,n,temp;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(i=n/2;i>=1;i--)
		/*HeapAdjust1(i,n);*/
		HeapAdjust2(i,n);
		for(i=n;i>=2;i--)
		{
			temp=a[1];
			a[1]=a[i];
			a[i]=temp;
			HeapAdjust(1,i-1);
		}
		for(i=1;i<=n;i++)
			printf("%4d",a[i]);
		printf("\n");
	}
	return 0;
}
posted on 2011-04-12 20:08  奋斗青春  阅读(386)  评论(0编辑  收藏  举报