这两天看了下堆排序, 意思是理解了,不过还没找到用处。。。
先练练打字吧。。
堆排序(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; }