【算法面试宝典】十大经典排序算法 - 基数排序

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个指针。

猜你喜欢

转载自blog.csdn.net/u010482601/article/details/121641879