zoukankan      html  css  js  c++  java
  • 基数排序

    二话不说,先上代码:
    接下来将重点解释有important注释的地方:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1000005;
    long long origin[N],final[N],last[N];//原始数组,当前数组,原始数组当前的关键字 
    int bucket[12];//桶 
    int cout=15;//位数,最大位数 
    int po(int a)//乘方函数 
    {
        int n=1;
        for(int i=1;i<a;++i)
        {
            n*=10;
        }
        return n;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&origin[i]);
        }
        for(int i=0;i<=cout;++i)
        {
            memset(bucket,0,sizeof(bucket));
            for(int j=1;j<=n;++j)//取出马上要排序的关键字,一般从个位开始往上取。 
            {
                last[j]=(origin[j]/po(i))%10;
                bucket[last[j]]++;//桶排操作 
            }
            for(int j=1;j<=9;++j)//求前缀和操作,就是看当前关键字,可以大概由小到大排到多少位,方便下面对最终数组进行排序! 
            {
                bucket[j]+=bucket[j-1];//☣
            }
            for(int j=n;j>=1;--j)//important 
            {
                final[bucket[last[j]]]=origin[j];
                bucket[last[j]]--;//important
            }
            for(int j=1;j<=n;++j)//赋值操作 
            {
                origin[j]=final[j];
            }
        }
        for(int i=1;i<=n;++i)//输出 
        {
            printf("%d ",final[i]);
        }
        return 0;
    }
    

    P.s:前缀和指当前所求关键字,加上自己同类的干扰(关键字一样)由小到大排到的位置(排到自己同类的最后面,最坏情况)。

    重点来了!!!

    important就是重点,首先我们可以发现,这里的for循环和前面的for循环有点不太一样,这个我们稍后作解释,我们先来解释一下下面的三重括号,最里面一重是当前原来数组(origin)的最后一位数;第二重就是这个最后一位数所在的桶的大概位置(前面求了前缀和,前缀和概念见前面P.s)这就是他final的位置,这个时候为了防止对后面一样的关键字有影响(两个关键字排在同一位置),所以对他的前缀和进行--操作,反正考虑的是最坏情况,也就是说,一来初始的前缀和一定是当前关键字所在桶的最后一位,所以我们进行--操作最多也就是减到第一位,并不会影响到前面一个桶,(若他是第一个桶,我相信大家照这个理解会更容易一些!)。
    相信大家上面都懂了,现在我们来讲一讲细节!!!
    为什么上面的for循环要反着写?
    为了使我们的解释更加方便,我们在这里为大家造一组数据:

    32 31 23 24

    你可能会说,看上去貌似没有什么问题啊? 别急!!
    首先我们先进行第一波排序,这一波以个位为关键字:
    结果如下:

    31 32 23 24

    正常,对吧!
    再来,重点来了,大家可以仔细品读下面这段话!
    第二波因为是从前往后对关键字为十位来进行排序,那我们慢慢来:
    1、首先23,24会被丢进二号桶,31,32会被扔进3号桶,所以2,3号桶各两个量,3号桶的前缀和为4,2号桶为2.

    _2、下面进行从前往后遍历:
    _

    (1)首先,31,3号桶,前缀和4,扔入final数组4号位
     
      (2)其次,32,3号桶,前缀和4--=3,扔入final数组3号位(细心的朋友应该已经发现问题了!)
      
     (3)再其次,23,2号桶,前缀和2,扔入final数组2号位
     
      (4)最后,24,2号桶,前缀和2--=1,扔入final数组1号位( 又出现了同样的问题,哈哈!)
    

    _3_最后的扯皮答案:

    24 23 32 31

    大家都应该知道问题在哪里了吧!因为我们要遵守优先级规则,后面的origin数组中低位一定比高位大,所以我们必须从后面开始排,否则会出现如果高位关键字的大小是一样的,那么考前面低位更小的排入final数组中反而会占据优先级更大的位置(也就是说31会在32后面!!!)

    如果你是一个皮怪,“我就想这样写!!!”,你可以这样做,首先优先级变为前面所有桶的大小+1(这一步忒麻烦,还要多定一个数组,唉!),然后后面的for循环你就可以正着写,最后把--改为++;
    以上就是我对这道题的所有解读,希望可以帮助到你!!!,谢谢采纳!

  • 相关阅读:
    正则 匹配 HTML 标签
    webpack 打包图片 能否提高加载速度
    禁止手机浏览器左右滑屏 后退 前进
    Objective-C--@property,@synthesize关键字介绍
    ios--绘图介绍
    iOS--为视图添加阴影
    iOS--iOS7摄像头识别二维码功能
    iOS--日历事件的获取和添加
    iOS-#ifdef DEBUG代码块介绍
    如何将你的程序打包成ipa
  • 原文地址:https://www.cnblogs.com/mudrobot/p/13330774.html
Copyright © 2011-2022 走看看