堆排序

来源:互联网 发布:淘宝发布宝贝怎么预览 编辑:程序博客网 时间:2024/06/13 04:58
//堆排序的根据是什么,就是每个堆的顶部的元素一定是最小值,那么我先建一个堆,每次记录下堆顶元素,然后把重新排列(这里有点技巧),减少堆的元素个数。
//注意堆的n是会变化,所以要先记录下来。
//处于同一层的节点大小不能判断,所以每次提取了堆顶元素就必须重新维护一次。(代码在sort部分)
#include <stdio.h>int a[101];int n;void down(int i){    int temp,t;    while(i*2<=n)    {        if (a[i]>a[i*2])        t=i*2;        else        t=i;    if ((i*2+1<=n)&&(a[t]>a[i*2+1]))        t=i*2+1;    if (t!=i)    {        temp=a[t];        a[t]=a[i];        a[i]=temp;        i=t;    }    else break;    }    return;}int sort(){    int t;    t=a[1];//每次先记录下堆顶的元素    a[1]=a[n];//修改堆顶的元素,再对堆进行整理    n--;//注意是先将元素个数减少一个,再维护(因为此时第一个元素已经被拿出,换成了最后一个元素,即原本最后一个元素的位置不需要了)    down(1);    return t;} int main() {     int i,num;     scanf("%d",&n);     num=n;//注意了这里的n是会变化的,所以要先记录下n的值(好吧,我查了好久才找到错这~~)   for (i=1;i<=n;i++)    scanf("%d",&a[i]);   for (i=n/2;i>=1;i--)     down(i);    for (i=1;i<=num;i++)    printf("%d ",sort());       printf("\n");        return 0; }



//这种方式无法用原来数组来保存元素,即是在原来的堆上进行修改得到的数据,那么有没有一种结果本身就是用堆来保存的从小到大的方法呢


//第二种方法就是先建立最大堆,则堆顶元素一定为当前堆内的最大元素,把它放在堆尾,并n--,使其不会改变,接着如法炮制,找出第二大,第三大元素。。,直到只剩一个元素
//该方法最后得到的是堆内按照下标顺序,已经是从大到小有序的,而不是第一种方法,边输出,边找下一个元素,因而在某些特定要求下会更加方便~~
#include <stdio.h> int a[101]; int n; void down(int i) {     int temp,t;     while (i*2<=n)     {         if (a[i]<a[i*2])            t=2*i;         else t=i;         if ((i*2+1<=n)&&(a[t]<a[i*2+1]))            t=2*i+1;         if (t!=i)         {             temp=a[t];             a[t]=a[i];             a[i]=temp;             i=t;         }         else break;     } } void sort() {      int temp;     while (n>1)    {     temp=a[n];     a[n]=a[1];//此时堆顶元素就是最大值     a[1]=temp;//因此将堆顶元素与最后一个元素交换     n--;//最后一个元素已经确定(位置是正确的),只需再对前n-1个数进行同样的考察     down(1);    } } int main() {  int i,num;  scanf("%d",&n);  num=n;//同样要先记录下n  for (i=1;i<=n;i++)    scanf("%d",&a[i]);    for (i=n/2;i>=1;i--)        down(i);//建立最大堆    sort();    for (i=1;i<=num;i++)        printf("%d ",a[i]);    return 0; }


0 0
原创粉丝点击