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

    基数排序

    一、  什么叫基数

    在数学上,基数(cardinal number)是集合论中刻画任意集合大小的一个概念。两个能够建立元素间一一对应的集合称为互相对等集合。根据对等这种关系对集合进行分类,凡是互相对等的集合就划入同一类。这样,每一个集合都被划入了某一类。任意一个集合A所属的类就称为集合A的基数,记作|A|(或cardA)。这样,当A 与B同属一个类时,A与B 就有相同的基数,即|A|=|B|。而当 A与B不同属一个类时,它们的基数也不同。

    二、  基数排序

    基数排序(radix sort)属于“分配式排序”(distribution sort)。讲到分配时排序了,这里再细说一下排序根据其所用的思想或方法将其分为五种,分别是 交换排序(冒泡排序、快速排序),插入排序(直接插入排序、希尔排序),选择排序(直接选择排序、堆排序),归并排序分配排序(桶排序、基数排序)。

    基数排序是对通排序的优化,相比通排序,基数排序所用的桶更少,通排序进行排序时所用到的桶的数量根据实际情况而定,一般会非常多,而基数排序中用到的桶的数量和所分配集合的基数数量是相同的,一般较少。例如我们对属于[1,1000]的n个元素进行桶排序,会用到1000个桶,如果是基数排序则只用10个桶。

    基数排序的每趟排序时用到了“桶”,所以又称其为“桶子法”(bucket sort或bin sort),顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。

    三、  具体排序演练

    例如我们对{11,41,24,39,78,35,26,36,42,15}这十个数进行排序。

    首先我们进行第一次分配,选取的基数是个位上的数,个位上的数是属于[0,9],所以做十个桶,把这些数放到这十个桶中。

    第一个桶,个位是0的数:{}

    第二个桶,个位是1的数:{11,41}

    第三个桶,个位是2的数:{42}

    第四个桶,个位是3的数:{}

    第五个桶,个位是4的数:{24}

    第六个桶,个位是5的数:{35,15}

    第七个桶,个位是6的数:{26,36}

    第八个桶,个位是7的数:{}

    第九个桶,个位是8的数:{78}

    第十个桶,个位是9的数:{39}

    分配完成之后我么再把这些数据按照桶的顺序收回到一个集合里

    {11,41,42,24,35,15,26,36,78,39}

    这个时候我们发现这些数他们的个位都是递增的,接下来我们再对其上一位(十位)继续分配即可。还是做十个桶。

    第一个桶,十位是0的数:{}

    第二个桶,十位是1的数:{11,15}

    第三个桶,十位是2的数:{24,26}

    第四个桶,十位是3的数:{35,36,39}

    第五个桶,十位是4的数:{41,42}

    第六个桶,十位是5的数:{}

    第七个桶,十位是6的数:{}

    第八个桶,十位是7的数:{78}

    第九个桶,十位是8的数:{}

    第十个桶,十位是9的数:{}

    分配完成之后我么再把这些数据按照桶的顺序收回到一个集合里

    {11,15,24,26,35,36,39,41,42,78,}

    这个时候就排序完成了。

    四、  Java代码实现

     

    public class RadixSort{

       

        public static void main(String[] args) {

           int []s={11,15,45,47,48,46,43,25,15,48};

           radix(s,2);

           for(int i:s)

               System.out.print(i+" ");

        }

        public static void radix(int []s,int distance){

           int[][]s2 = new int[10][s.length];//做桶

          

           int []size = new int[10];//记录每个桶里装的数据的数目

          

           int bit = 1;//表示位(个位,十位,百位,,,)

           while(distance>0){

               //把各个桶里的数据数目清零

               for (int i = 0; i < 10; i++)

                  size[i] = 0;

               //第一步,先把数据分到各个桶里

               bit *= 10;

               for(int i = 0 ; i < s.length ; i++){

                  int index = s[i]%bit/(bit/10);//获得对应位上的数

                  s2[index][size[index]] = s[i];

                  size[index]++;

               }

               //第二步,把各个桶里的数据在放回到原数组中

               int index = 0;

               for(int i=0;i<s2.length;i++){

                  for(int j=0;j<size[i];j++)

                      s[index++] = s2[i][j];  

               }

               distance--;

           }

        }

    }

     

    运行结果:11 15 15 25 43 45 46 47 48 48

    五、  基数排序的应用

    基数排序适用于对含有多个基本特性的元素进行排序,例如对时间进行排序,时间有年月日,我们发现其他排序太难对时间进行排序了,而我们的基数排序就轻而易举的完成了,先根据日进行分通排序,再根据月分桶排序,最后根据年进行分桶排序,就完成了。

                                                               ----------亓慧杰

  • 相关阅读:
    Linux入门之常用命令(14) kill
    【JVM命令系列】jstack
    【JVM命令系列】javap
    【JVM命令系列】jmap
    Hadoop安全(2)——————UserGroupInformation
    Hadoop安全(1)——————美团Hadoop安全实践
    软件测试流程进阶----两年软件测试总结
    每个程序员应该阅读的10本书籍
    成为优秀程序员的黄金10条法则
    Java异常的深入研究与分析
  • 原文地址:https://www.cnblogs.com/JCxiangbei/p/6755501.html
Copyright © 2011-2022 走看看