基数排序(radix sort)属于分配式排序,又称桶子法或bin sort,它是透过键值的部分咨讯,将要排序的元素分配至某些桶中,藉以达到排序的作用,基数排序法属于稳定的排序,其时间复杂度为O (nlog( r )m),其中r为所采取的基数,m为堆数,在某些时候,基数排序法的效率高于其他的稳定性排序算法。
参考百科:
第一步
以LSD为例,假设原来有一串数值如下所示:
73, 22, 93, 43, 55, 14, 28, 65, 39, 81
首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:
0
1 81
2 22
3 73 93 43
4 14
5 55 65
6
7
8 28
9 39
第二步
接下来将这些桶子中的数值重新串接起来,成为以下的数列:
81, 22, 73, 93, 43, 14, 55, 65, 28, 39
接着再进行一次分配,这次是根据十位数来分配:
这时候整个数列已经排序完毕;如果排序的对象有三位数以上,则持续进行以上的动作直至最高位数为止。
LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好。MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。
实现方法
最高位优先(Most Significant Digit first)法,简称MSD法:先按k1排序分组,同一组中记录,关键码k1相等,再对各组按k2排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd对各子组排序后。再将各组连接起来,便得到一个有序序列。
最低位优先(Least Significant Digit first)法,简称LSD法:先从kd开始排序,再对kd-1进行排序,依次重复,直到对k1排序后便得到一个有序序列。
C++实现:
//
// main.cpp
#include <iostream>
using namespace std;
int max_bit(int *a,int n){//辅助函数,求数据的最大位数
int d=1;
int p=10;
for (int i=0; i<n; i++) {
while (a[i]>=p) {
p=p*10;
d++;//a[i]<10=>一位数,a[i]>10=>两位数,以此类推
}
}
return d;
}
void radix_sort(int *a ,int n){
int tmp[10];
int count[10];
int d=max_bit(a, n);
int r=1;
for (int idx=0; idx<d; idx++) {
for (int i=0; i<10; i++) {//装桶之前要先清桶
count[i]=0;
}
for (int i=0; i<n; i++) {
int k=a[i]/r;//先除以r
int q=k%10;//再取余 得到a[i]的某一位数:个位或者十位等等
count[q]++;//每个桶存了几位数
}
for (int i=1; i<10; i++) {
count[i]+=count[i-1];
}
for (int j=n-1; j>=0; j--) {//这里就是每次从按照个位数或十位数之类的分类的桶排序放好的地方
int p=a[j]/r;
int s=p%10;
tmp[count[s]-1]=a[j];
count[s]--;//count[s]里拿出了一个数了
}
for (int i=0; i<n; i++) {
a[i]=tmp[i];
}
r=r*10;
}
}
int main(int argc, const char * argv[]) {
int a[]={73,22,93,43,55,14,28,65,39,81};
radix_sort(a, 10);
for (int i=0; i<10; i++) {
cout<<a[i]<<" ";
}
return 0;
}