1 解题思路
基数排序的核心思想是把要比较的元素拆分,按照个位、十位、百位、千位的来拆分,然后在相同位上的数值放入从0-9的10个桶中,这样相同位上的数值就有序了,然后依次类推进行比较,最终得到排好序的元素列表。
基数排序有两种方式,一种是最高位优先(Most Significant Digit first)法,简称MSD法。一种是最低位优先(Least Significant Digit first)法,简称LSD法。
示例:
输入:nums = {80, 55, 70, 50, 66, 70, 71, 91, 90, 98, 99, 82, 85, 101, 78, 77, 76, 68, 50, 54}
输出:nums = {50, 50, 54, 55, 66, 68, 70, 70, 71, 76, 77, 78, 80, 82, 85, 90, 91, 98, 99, 101}
第一步:遍历个位的数值,放入0-9的桶中
桶 0 :80,70,50,70,90,50
桶 1 :71,91,101
桶 2 :82
桶 3 :
桶 4 :54
桶 5 :55,85
桶 6 :66,76
桶 7 :77
桶 8 :98,78,68
桶 9 :99
然后合并桶中的元素得到数组:
nums = {80,70,50,70,90,50,71,91,101,82,54,55,85,66,76,77,98,78,68,99}
第二步:遍历十位的数值,放入0-9的桶中
桶 0 :101
桶 1 :
桶 2 :
桶 3 :
桶 4 :
桶 5 :50,50,54,55
桶 6 :66,68
桶 7 :70,70,71,76,77,78
桶 8 :80,82,85
桶 9 :90,91,98,99
然后合并桶中的元素得到数组:
nums = {101,50,50,54,55,66,68,70,70,71,76,77,78,80,82,85,90,91,98,99}
第三步:遍历百位的数值,放入0-9的桶中
桶 0 :50,50,54,55,66,68,70,70,71,76,77,78,80,82,85,90,91,98,99
桶 1 :101
桶 2 :
桶 3 :
桶 4 :
桶 5 :
桶 6 :
桶 7 :
桶 8 :
桶 9 :
然后合并桶中的元素得到数组:
nums = {50,50,54,55,66,68,70,70,71,76,77,78,80,82,85,90,91,98,99,101}
可以看到数组已经是有序了。
2 编码实现
public static void binSort(int[] nums,int order){
int[][] tmpNums = new int[10][nums.length];//二维数组,数组的第一维标识可能的余数0-9
int[] seat = new int[10];//记录元素在二维数组中的位置
int m = 1;//从哪一位开始循环排序
int t = 1;//十位除以10,百位除以100
int mark = 0;//元素下标
int k = 0;//目标数组下标;
while (m<=order) {
//把待排序元素放入二维数组中
for (int i = 0; i < nums.length; i++) {
mark = (nums[i]/t)%10;
tmpNums[mark][seat[mark]++] = nums[i];
}
//把二维数组中的元素放入目标数组中
for (int i = 0; i < 10; i++) {
if(seat[i] != 0) {
for (int j = 0; j < seat[i]; j++) {
nums[k++] = tmpNums[i][j];//二维数组的值放入目标数组中
}
}
seat[i] = 0;//清空一维数组的值,以便下次使用
}
m++;
t = 10*t;
k = 0;
}
编码的实现对应解题思路的步骤可以分析一下:使用二维数组来存储排序中的元素,二维数组的第一维表示0-9的桶。执行过程如下所示:
第一步:
80 70 50 70 90 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0
71 91 101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
54 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
55 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
66 76 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
98 78 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
第二步:
101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
50 50 54 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
66 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
70 70 71 76 77 78 0 0 0 0 0 0 0 0 0 0 0 0 0 0
80 82 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
90 91 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
第三步:
50 50 54 55 66 68 70 70 71 76 77 78 80 82 85 90 91 98 99 0
101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 时间复杂度和空间复杂度
设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度 T(n) = O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。 空间效率:需要2*radix个指向队列的辅助空间,以及用于静态链表的n个指针。