1. 程式人生 > 實用技巧 >陣列排序-基數排序(Radix Sort)

陣列排序-基數排序(Radix Sort)


概念:

基數排序屬於“分配式排序”,又稱“桶子法”,顧名思義,它是透過鍵值的部分資訊,將要排序的元素分配至某些“桶”中,即以達到排序的作用,基數排序法是屬於穩定性的排序,其時間複雜度為O(nlog(r)m),其中r為所採取的基數,而m為堆數,在某些時候,基數排序法的效率高於其它的穩定性排序法。


實現方法:

最高位優先(Most Significant Digit first)法,簡稱MSD法:先按k1排序分組,同一組中記錄,關鍵碼k1相等,再對各組按k2排序分成子組,之後,對後面的關鍵碼繼續這樣的排序分組,直到按最次位關鍵碼kd對各子組排序後。再將各組連線起來,便起到一個有序序列。
最低位優先(Least Significance Digit first)法,簡稱LSD法:先從kd開始排序,再對kd-1進行排序,依次重複,直到對k1排序後便得到一個有序序列。


實現原理:

基數排序的發明可以追溯導1887年,赫爾曼·何樂禮在打孔卡片製表機(Tabulation Machine)上的貢獻。它是這樣實現的:將所有待比較數值(正整數)統一為同樣的數位長度,數位較短的數前面補零。然後,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後,數列就變成一個有序序列。
基數排序的方式可以採用LSD(Least significance digital)或MSD(Most significance digital),LSD的排序方式由鍵值的最右邊開始,而MSD則相反,由鍵值的最左邊開始。


示例:

package com.cnblogs.lxj.testarraysort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @packageName: com.cnblogs.lxj.testarraysort
 * @className: RadixSort
 * @description: 測試基數排序
 * @author: liuxiaojiang
 * @date: 2021/1/8
 */
public class RadixSort {

    public static void main(String[] args) {
        int[] a = new int[]{321,1,10,60,577,743,127};
        printArray(a);
        radixSortOne(a,10,3);
        printArray(a);
    }

    /**
     * @description: 基數排序方法(1)
     * @author: liuxiaojiang
     * @date: 2021/1/8
     * @param a: 代表陣列
     * @param radix: 代表基數
     * @param d: 代表排序元素的位數
     * @return: void
     **/
    public static void radixSortOne(int[] a,int radix,int d){
        List<List<Integer>> ts = new ArrayList<List<Integer>>();
        int rate = 1;
        for(int i = 0;i < radix;i++){
            List<Integer> t = new ArrayList<Integer>();
            ts.add(t);
        }
        for(int i = 0;i < d;i++){
            for(int j = 0;j < radix;j++){
                List<Integer> t = ts.get(j);
                t.clear();
            }
            for(int j = 0;j < a.length;j++){
                int subKey = (a[j]/rate) % radix;
                List<Integer> t = ts.get(subKey);
                t.add(a[j]);
            }
            int count = 0;
            for(int j = 0; j < radix;j++){
                List<Integer> t = ts.get(j);
                for(int k = 0;k < t.size();k++){
                    a[count++] = t.get(k);
                }
            }
            rate *= radix;
            System.out.print("第"+(i+1)+"次:");
            printArray(a);
        }
    }

    /**
     * @description: 基數排序方法(2)
     * @author: liuxiaojiang
     * @date: 2021/1/8
     * @param array: 代表陣列
     * @param radix: 代表基數
     * @param d: 代表排序元素的位數
     * @return: void
     **/
    public static void radixSortTwo(int[] array,int radix,int d){
        int[] tempArray = new int[array.length];
        int[] count = new int[radix];
        int rate = 1;
        for(int i = 0;i < d;i++){
            Arrays.fill(count,0);
            System.arraycopy(array,0,tempArray,0,array.length);
            for(int j = 0;j < array.length;j++){
                int subKey = (tempArray[j] / rate) % radix;
                count[subKey]++;
            }
            for(int j = 1;j < radix;j++){
                count[j] = count[j] + count[j - 1];
            }
            for(int m = array.length - 1;m >= 0;m--){
                int subKey = (tempArray[m] / rate) % radix;
                array[--count[subKey]] = tempArray[m];
            }
            rate *= radix;
            System.out.print("第"+(i+1)+"次:");
            printArray(array);
        }
    }

    /**
     * @description: 輸出方法
     * @author: liuxiaojiang
     * @date: 2021/1/8
     * @param array: 代表陣列
     * @return: void
     **/
    public static void printArray(int[] array){
        for(int i : array){
            System.out.print(i+" ");
        }
        System.out.println();
    }

}

執行結果:

321 1 10 60 577 743 127       //初始化
第1次:10 60 321 1 743 577 127 
第2次:1 10 321 127 743 60 577 
第3次:1 10 60 127 321 577 743 
1 10 60 127 321 577 743       //最終結果

原理: