基数排序

基数排序

一、  什么叫基数

在数学上,基数(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

五、  基数排序的应用

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

 

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

posted on 2017-04-24 10:14  JC向北  阅读(518)  评论(0编辑  收藏  举报

导航