【数据结构与算法】基数排序

基数排序是一种多关键字排序。以扑克牌排序为例,每张扑克牌有两个“关键码”:花色和面值,花色的权重大于面值,如红桃A小于黑桃2。
通常有最高位优先MSD (Most Significant Digit first)和最低位优先LSD (Least Significant Digit first)两种实现方式。

1、低位优先LSD
(1)最低位优先法首先依据最低位关键码Kd对所有对象进行一趟排序
(2)再依据次低位关键码Kd-1对上一趟排序的结果再排序
(3)依次重复,直到依据关键码K1最后一趟排序完成,就可以得到一个有序的序列。
使用这种排序方法对每一个关键码进行排序时,不需要再分组,而是整个对象组都参加排序。
【数据结构与算法】基数排序_第1张图片
可以看出在进行每次排序时,直接根据上一次排序结果的当前位数值规则进行排序,没有其他限制条件。如第二次排序时,将{720,355,436,457,657,329,839}根据其第二位数值顺序{2,5,3,5,5,2,3}进行排序就可以了。
2、高位优先MSD
(1) 先根据最高位关键码K1排序,有多少不同的K1码就需要分成多少组。K1码相同的元素被分在同一个组,如果此组内有多个元素,则需要继续排序确定大小关系。
(2) 分别对元素多于一个的每个K1组根据关键码K2进行排序,按K2值的不同,再分成若干个更小的K2子组,每个子组中的元素具有相同的K1和K2值。
(3) 依此重复,直到每个组都只有一个元素或对关键码Kd完成排序为止。
(4) 最后,把所有子组中的元素依次连接起来,就得到一个有序的元素序列。
【数据结构与算法】基数排序_第2张图片
可以看出,MSD除了第一次排序时限制,之后的排序都不能只根据当前位的数值规则,还要根据上一次排序的结果中是否处于同一组。如第二次排序时,因第一次排序{339,338,355}和{457,436}是不同的组,故只能分别根据{3,3,5}和{5,3}进行第二次排序。如果完全根据第二位数值规则{3,3,5,5,3,5,2}对第一次结果排序,则会得到错误的结果。
3、LSD和MSD的区别
可以看出,LSD实现更简单。原因:高位关键码的权重大于低位关键码,不论元素的低位如何排序,元素的高位有“一位否决权”,而元素的高位排序确定时,低位只能局部调整。即LSD时,按照当前位的数值大小排序永远是正确的。而MSD时,当前位的数值大小有可能破坏高位的排序结果,因而只能微调(组内排序)。

每次排序采用计数排序,LSD的代码如下:

    public static void radixSort_LSD(int[] nums,int base, int maxBits) {
        int len = nums.length;
        int[] temp = new int[len];
        int[] count = new int[base];
        int divide = 1;

        for (int i = 0; i < maxBits; i++) {

            System.arraycopy(nums, 0,temp, 0, len);
            Arrays.fill(count, 0);

            for (int j = 0; j < len; j++) {
                int tempKey = (temp[j]/divide)%base;
                count[tempKey]++;
            }

            for (int j = 1; j < base; j++) {
                count [j] = count[j] + count[j-1];
            }
            for (int j = len - 1; j >= 0; j--) {
                int tempKey = (temp[j]/divide)%base;
                count[tempKey]--;
                nums[count[tempKey]] = temp[j];
            }
            divide = divide * base;
        }
    }

你可能感兴趣的:(数据结构与算法)