1.基本思想
它是根据关键字中各位的值,通过对排序的N个元素进行若干趟“分配”与“收集”来实现排序的。
不需要比较关键字的大小。
将基数排序分为LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由数值的最右边(低位)开始,而MSD则相反,由数值的最左边(高位)开始。注意:LSD的基数排序适用于位数少的数列,如果位数多的话,使用MSD的效率会比较好。
MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。
示例:
2.算法分析
时间复杂度:O(dn) (d即表示整形的最高位数)
空间复杂度:O(10n) (10表示0~9,用于存储临时的序列)
稳定性:稳定
3.算法实现:
<span style="white-space:pre"> </span>public static void radixSort(int[] array,int distance){
//distance 代表排序元素的位数
int radix =10; //radix 代表基数 ,0-9,10个
int len = array.length;
int[] count = new int[radix];
int[][] tmp = new int[radix][len+1];
int divide = 1;
for(int i = 0; i < distance; i++){
//按位数上数字分配到各个数组中
for(int j = 0; j < len; j++){
int tmpkey = (array[j]/divide)%10;
int index = ++count[tmpkey];
tmp[tmpkey][index] = array[j];
}
//整合
for(int j = 0 ,k =0; j < radix; j++){
for (int x = 1; x <= count[j]; x++){
array[k++] = tmp[j][x];
}
count[j] = 0; //复位
}
divide *= radix;
}
}
注:需要引入Arrays类,import java.util.Arrays;
3.算法优化:
因为上述基数排序,需要设置一个10*n 的临时数组来储存变量,空间利用率不高。 以下考虑基于计数的基数排序。计数排序是什么意思呢?假设数序列中小于元素a的个数为n,则直接把a放到第n+1个位置上。
通过结合这两者,空间复杂度降为O(n)。
以个位数为例,通过记录各radix的数量来判断有多少数是小于当前这个radix的,再逆序(保证算法的稳定性)插入相应位置即可。
//基于计数的基数排序
public static void radixSort2(int[] array,int distance){
//distance 代表排序元素的位数
int radix =10; //radix 代表基数 ,0-9,10个
int len = array.length;
int[] tmp = new int[len];
int[] count = new int[radix];
int divide = 1;
for(int i = 0; i < distance; i++){
System.arraycopy(array, 0,tmp, 0, len); //复制数组
Arrays.fill(count, 0); //将计数数组置0
//计数
for(int j =0; j < len; j++){
int tmpkey = (array[j]/divide)%10;
count[tmpkey]++;
}
for(int j = 1; j < radix; j++){
count[j] += count[j-1];
}
//逆序,保证数组的稳定性
for(int j = len -1; j >= 0; j--){
int tmpKey = (tmp[j]/divide)%radix;
count[tmpKey]--;
array[count[tmpKey]] = tmp[j];
}
divide *= radix;
}
}