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

    堆排时间复杂度为O(n log n),比快排稳定

    这次先贴代码emmm

    下次有空再来补解析

    自我感觉注释很详细了

     1 #include <cstdio>
     2 int n,m,a[5000005];    //建立大根堆,从小到大排序 
     3 void add(int x,int id)    //往堆中添加节点 
     4 {
     5     int fa;  //  父节点 
     6     a[id]=x;    //把新节点放在堆的最后 
     7     //整理堆,使堆始终保持大根堆的性质 
     8     while (id>1 && a[id/2]<a[id])    // 如果该节点不是堆的根,并且大于它的父亲节点,那么不符合大根堆的性质 
     9     {                             //调整 
    10         fa=id>>1;
    11         a[fa]^=a[id];  a[id]^=a[fa];  a[fa]^=a[id];    //和父亲节点交换 
    12         id=fa;                                     //节点上移,继续调整 
    13     } 
    14 //因为只有当儿子节点大于父亲节点时才交换,所以最后新节点一定大于它的两个儿子节点
    15 //当新节点小于父亲节点时停止交换
    16 //这样就保持了大根堆的性质 
    17     return;
    18 }
    19 void heapsort()        //开始堆排 
    20 {
    21 //每次把根和堆的最后一个节点交换
    22 //就是把根取出,暂存在最后,然后整理堆中剩下的节点,找出剩余节点中最大的 
    23 //因为是大根堆,每次取出的根节点都是剩余节点中最大的
    24 //所以下一次取出的节点肯定比上一次小 
    25 //每次都把取出的根节点放在当前堆的最后
    26 //所以最后数组从后往前是递减的
    27 //所以大根堆排序是从小到大的 
    28     while (m>1)    //当堆中只剩下一个节点时,不用再整理了 
    29     {
    30         int ls,rs,son,i=1;
    31         //  ls  左儿子下标  
    32         //  rs  右儿子下标
    33         //  son  要和当前节点交换的儿子下标  
    34         while (i*2<=m)  //儿子还在当前堆的范围内 
    35         {
    36             ls=i<<1;  rs=ls|1;  
    37             son=(rs<=m && a[rs]>a[ls])?rs:ls;  //  找出两个儿子中较大的 
    38             if (a[i]>=a[son]) //说明当前节点大于它的两个儿子节点 
    39                break;    //结束 
    40             a[i]^=a[son];  a[son]^=a[i];  a[i]^=a[son];  //  交换后父节点不小于两个子节点 
    41             i=son;      //如果没有结束,说明还需要交换,继续 
    42         }
    43         a[m]^=a[1];  a[1]^=a[m];  a[m]^=a[1];  m--;
    44         //  把根结点放在当前堆的最后 ,减小堆的范围 
    45     }
    46     return;
    47 }
    48 int main()
    49 {
    50     int i,j,x;
    51     scanf("%d",&n);
    52     scanf("%d",&a[1]);  
    53     for (i=2;i<=n;i++)
    54     {
    55         scanf("%d",&x);
    56         add(x,i);
    57     } 
    58     //添加完节点的堆是一个大根堆 
    59     a[n]^=a[1];  a[1]^=a[n];  a[n]^=a[1];  m=n-1;
    60     //  把根结点放在当前堆的最后 ,减小堆的范围
    61     heapsort();
    62     for (i=1;i<=n;i++)
    63        printf("%d ",a[i]);
    64     return 0;  
    65 }

    测试了一下发现堆排的速度果然还是比不上C++的sort

  • 相关阅读:
    使用本地系统帐户和域用户帐户两者区别(microsoft SQLServer2000)(ZT)
    Winform中消息循环、异步操作、Control.Invoke&Control.BeginInvoke学习
    SQL字符串的分组聚合(ZT)
    一次项目维护案例而对事务学习的笔记
    NOIP2011提高组 选择客栈
    NOIP2012提高组 Day 2 Problem 2 借教室
    201793模拟赛T2 取数(win)
    201793模拟赛T1 卡片(card)
    01Dart 变量常量
    01TypeScript 基础类型
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/14033594.html
Copyright © 2011-2022 走看看