基数排序(Radix Sort)也是一种非比较型的排序算法,适用于大规模数据的排序。它通过将数字分解为多个关键字位进行排序,通常使用计数排序作为子步骤。
基数排序主要有以下两个步骤:
- 按位排序:从最低有效位(LSD:Least Significant Digit)开始,对数字进行排序,然后逐渐向最高有效位(MSD:Most Significant Digit)移动。
- 多轮排序:对每一位使用稳定的排序算法(如计数排序)进行排序。
一般的数字都是按10进制基数进行排序,个位,十位,百位依次进行排序。
如待排序数组:[12,234,6,88,36,45]
先按个位进行排序结果:[12, 234, 45, 6, 36, 88]
按十位进行排序结果:[6, 12, 234, 36, 45, 88]
按百万进行排序结果:[6, 12, 36, 45, 88, 234]
最后完成了排序。每位排序这里可以使用计数排序,因为每位数字范围是0-9是固定的。
代码实现:
public void sort(int[] arr){
//取最大值
int max = findMaxVal(arr);
/**
* 按位进行排序,radix是基数(个,十、百、千...),依次取值:[1,10,100,1000...]
*/
for(int radix=1;max/radix >0 ;radix *=10){
countSort(arr,radix);
}
}
/**
* 按位(个、十、百)进行计数排序
* @param arr
* @param radix 基数,个位1,十位10,百位100
*/
void countSort(int[] arr,int radix){
int size = arr.length;
//计数排序 统计数组初始化 ,每个位置数字范围0-9,所有统计数组长度10
int[] count = new int[10];
Arrays.fill(count,0);
/**
* 位数字计数
* 位数字 = (value/radix) % 10
* value是当前元素,radix是基数。
* 如数字 798 对用取个位 (798/1)%10 = 8,十位 (798/10)%10 = 9
*/
for (int i = 0; i < arr.length; i++) {
count[(arr[i]/radix) % 10] +=1;
}
//累加计数结果
for (int i = 1; i < 10; i++) {
count[i] += count[i-1];
}
//输出有序结果
int[] outArr = new int[size];
for (int i = size-1; i >=0 ; i--) {
//索引等于位数字 和前面位数字计数计数方式相同
int index = (arr[i] / radix) % 10;
outArr[count[index] - 1] = arr[i];
count[index]--;//计数-1
}
//将有序数组复制到原数组
for (int i = 0; i < size; i++) {
arr[i] = outArr[i];
}
System.out.println(Arrays.toString(arr));
}
int findMaxVal(int[] arr){
int max = 0;
for (int i = 0; i < arr.length; i++) {
if(max < arr[i]) max = arr[i];
}
return max;
}
基数排序的时间复杂度为O(n⋅k),其中 n 是待排序元素的数量,k是数字的位数。