• 堆排序


    5.3.3.堆排序

    堆:设有数据元素的集合(R1,R2,R3,...Rn)它们是一棵顺序二叉树的结点且有

           Ri<=R2i 和Ri<=R2i+1(或>=)

    堆的性质:堆的根结点上的元素是堆中的最小元素,且堆的每一条路径上的元素都是有序的。

    堆排序的思想是:

    1)heapdown调整堆:每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)

    2)heapbuild建初始堆(将结点[n/2],[ n/2]-1,...3,2,1分别调成堆)

    3)heapsort

         建立初始堆,

           当未排序完时

             输出堆顶元素,删除堆顶元素,将剩余的元素重新建堆。

             方法:将堆顶元素与最后无序元素交换,调整堆顶元素。

      

    堆排序:稳定的nlog(n),只需要一个临时空间。

    每次可以在log(n)的时间复杂度内求无序数据的最值。应用在优先队列内。

    例题:3110 二叉堆练习3

    题目描述 Description

    给定N(N≤500,000)和N个整数(较有序),将其排序后输出。

    输入描述 Input Description

    N和N个整数

    输出描述 Output Description

    N个整数(升序)

    样例输入 Sample Input

    5

    12 11 10 8 9

    样例输出 Sample Output

    8 9 10 11 12

    数据范围及提示 Data Size & Hint

    对于33%的数据 N≤10000

    对于另外33%的数据 N≤100,000  0≤每个数≤1000

    对于100%的数据 N≤500,000  0≤每个数≤2*10^9

    程序如下:

    从小到大排序,建立大顶堆。

    写法一:数组做全局变量

    #include<stdio.h>

    #include<iostream>

    #include<stdlib.h>

    using namespace std;

    int n,len,a[500009];

    void heapdown(int i){每次向下调整堆顶元素

           int j;

           j=2*i;

           while(j<=n){ //可能多次进行,所以while语句调整

                  if(j<n&&a[j]<a[j+1])j++;

                  if (a[i]<a[j])swap(a[i],a[j]);

                  i=j;

                  j=2*i;

           }

    }

    void heapbuild(){//建立初始堆

        int i;

           for(i=n/2;i>0;i--)heapdown(i);

    }

    void heapsort(){//堆排序

           int i;

           heapbuild();      //建立初始堆,堆顶元素最大

           while(n>=2){

                  swap(a[1],a[n]);//将堆顶元素与最后无序元素交换

                  n--;//无序长度不断缩短

                  heapdown(1);   //堆顶元素可能是个较小的数,向下调整

           }

          

    }

    int main(){

           scanf("%d",&n);

           int i;

           len=n;

           for(i=1;i<=len;i++)

             scanf("%d",&a[i]);

           heapsort(); 

           for(i=1;i<=len;i++)

             printf("%d ",a[i]);

    }

    如果要进行多组数的堆排序,需要传递数组参数

    写法二:数组作为参数传递。

    #include<stdio.h>

    #include<iostream>

    #include<stdlib.h>

    using namespace std;

    int n,len,b[500009];

    void heapdown(int a[],int i,int size){

           int j;

           j=2*i;

           while(j<=size){

                  if(j<size&&a[j]<a[j+1])j++;

                  if (a[i]<a[j])swap(a[i],a[j]);

                  i=j;

                  j=2*i;

           }

    }

    void heapbuild(int a[],int size){

        int i;

           for(i=size/2;i>0;i--)heapdown(a,i,size);

    }

    void heapsort(int a[],int size){

           int i;

           heapbuild(a,size);   

           while(size>=2){

                  swap(a[1],a[size]);

                  size--;

                  heapdown(a,1,size);      

           }

          

    }

    int main(){

           scanf("%d",&n);

           int i;

           len=n;

           for(i=1;i<=len;i++)

             scanf("%d",&b[i]);

           heapsort(b,len); 

           for(i=1;i<=len;i++)

             printf("%d ",b[i]);

    }

  • 相关阅读:
    Ping pong
    [NOIp2015普及组]推销员
    [模板]树状数组
    [洛谷201704R1]开心派对小火车
    洛谷P3515 [POI2011]Lightning Conductor(决策单调性)
    bzoj1560:[JSOI2009]火星藏宝图(斜率优化)
    (转载)行走在镜面的边缘
    洛谷P4360 [CEOI2004]锯木厂选址(斜率优化)
    洛谷P4072 [SDOI2016]征途(斜率优化)
    洛谷P3648 [APIO2014]序列分割(斜率优化)
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5603892.html
Copyright © 2020-2023  润新知