算法熟记-排序系列-基数排序

1. 简述
1.1 一般方法

    计数排序的排序对象一般是整数。
    假设待排序数组为 int array[], 数组长度为n。
    第一步:开辟临时数组,int tmp[],数组长度为n。int count,数组长度为10。
    第二步:遍历数组,得到最大数值的位数d,即后面需要d次排序。
    第三步:根据个位进行排序,根据十位进行排序,···,根据d位进行排序。
               对于根据i位进行排序,其中1<=i<=d
               首先,统计array的所有元素在d位上的出现次数,保存到int count[]中。
               然后,根据count[]计算得到,array应该在tmp中的出现的最后的位置,即count[i]=count[i]+count[i-1], i>0。
               接着,从后向前遍历array,对于array[i],得到其位数在count的对应下标m(个位对应0,十位对应1,···),令tmp[count[m]--] = array[i]
                       上一步中之所以从后向前遍历array,是因为count恰好存储的是tmp中每个分组最后出现的位置。
               最后,将tmp内容,复制到array中。

1.2 一个更加抽象的伪代码:
    RADIX-SORT(A,d)
        for i = 1 to d
        使用一种稳定排序算法对A中元素的第i位进行排序
1.3 位数的顺序
      基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。
      即,一个是从低位到高位,另一个是从高位到低位。

2. 复杂度
    以简述中的方法分析,统计次数时间为n,计算count时间为10,基数分配时间为n,基数回收时间为n,基本上是d*(3*n+10)。 当然可以有一些优化。但是基本上,复杂度是O(d*(n+radix)),其中radix是关键码的取值范围。空间复杂度是O(n+radix)。   

    稳定性属于稳定的排序。注意,这里的稳定性是必须的,即针对每个位数分别进行排序必须是稳定的,只有这样,才能保证基数排序从高位开始还是从低位开始排序都是正确的。

3. 代码

// 辅助函数,求数据的最大位数
int  maxbit( int  data[], int  n)  { 
  
int  d  =   1 // 保存最大的位数
  int  p  = 10 ;   
  
for ( int  i  =   0 ;i  <  n; i ++ ) {
    
while (data[i]  >=  p) {
      p 
*=   10 ;
      d
++ ;
    }
  }
  
return  d;
}
// 基数排序
void  radixsort( int  data[], int  n)  { 
  
int  d  =  maxbit(data,n); 
  
int   *  tmp  =   new   int [n];
  
int   *  count  =   new   int [ 10 ];  // 计数器
   int  i,j,k;
  
int  radix  =   1 ;
  
for (i  =   1 ; i  <=  d; i ++ ) {   // 进行d次排序    
     for (j  =   0 ; j  <   10 ;j ++ // 每次分配前清空计数器  
     count[j]  =   0
    
for (j  =   0 ;j  <  n; j ++ ) {  // 统计每个桶中的记录数
      k  =  (data[j] / radix) % 10
      count[k]
++ ;
   }
    
for (j  =   1 ;j  <   10 ; j ++ // 将tmp中的位置依次分配给每个桶 
      count[j]  =  count[j - 1 +  count[j];
    
for (j  =  n - 1 ;j  >=   0 ;j -- ) {  // 将所有桶中记录依次收集到tmp中
    k  =  (data[j] / radix) % 10 ;
    count[k]
--
     tmp[count[k]] 
=  data[j];
    }
    
for (j  =   0 ;j  <  n;j ++ // 将临时数组的内容复制到data中
      data[j]  =  tmp[j];
    radix 
=  radix * 10 ;
  } 
  delete [] tmp;
  delete [] count;

4. 参考资料

    维基百科-基数排序    http://en.wikipedia.org/wiki/Radix_sort

你可能感兴趣的:(基数排序)