zoukankan      html  css  js  c++  java
  • 堆排序

    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]);

    }

  • 相关阅读:
    Spring 学习十五 AOP
    Spring 学习十四 Spring security安全
    博客文格式优化
    作为一名软件测试工程师,需要具备哪些能力
    单元测试工程师需要具备的任职资格
    初识安全测试(一)
    压力测试工具JMeter入门教程
    Jmeter的优点是什么?除了轻量级,它和LoadRunner有什么本质区别
    初识Jmeter(一)
    初识Selenium(四)
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5603892.html
Copyright © 2011-2022 走看看