排序算法 | 基數排序算法原理及實現和優化

基數排序不同於之前所介紹的各類排序,前邊介紹到的排序方法或多或少的是通過使用比較和移動記錄來實現排序,而基數排序的實現不需要進行對關鍵字的比較,只需要對關鍵字進行“分配”與“收集”兩種操作即可完成。

基數排序的原理


例如對無序表 {50,123,543,187,49,30,0,2,11,100} 進行基數排序,由於每個關鍵字都是整數數值,且其中的最大值由個位、十位和百位構成,每個數位上的數字從 0 到 9,首先將各個關鍵字按照其個位數字的不同進行分配分配表如下圖所示:

通過按照各關鍵字的個位數進行分配,按照順序收集得到的序列變爲:{50,30,0,100,11,2,123,543,187,49}。在該序列表的基礎上,再按照各關鍵字的十位對各關鍵字進行分配,得到的分配表如下圖所示:

由上表順序收集得到的記錄表爲:{0、100、2、11、123、30、543、49、50、187}。在該無序表的基礎上,依次將表中的記錄按照其關鍵字的百位進行分配,得到的分配如下圖所示:

最終通過三次分配與收集,最終得到的就是一個排好序的有序表:{0、2、11、30、49、50、100、123、187、543}。

例子中是按照個位-十位-百位的順序進行基數排序,此種方式是從最低位開始排序,所以被稱爲最低位優先法(簡稱“LSD法”)。

同樣還可以按照百位-十位-各位的順序進行排序,稱爲最高位優先法(簡稱“MSD法”),使用該方式進行排序同最低位優先法不同的是:當無序表中的關鍵字進行分配後,相當於進入了多個子序列,後序的排序工作分別在各個子序列中進行(最低位優先法每次分配與收集都是相對於整個序列表而言的)。

例如還是對{50,123,543,187,49,30,0,2,11,100}使用最高位優先法進行排序,首先按照百位的不同進行分配,得到的分配表爲:

由上圖所示,整個無序表被分爲了 3 個子序列,序列 1 和序列 2 中含有多個關鍵字,序列 3 中只包含了一個關鍵字,最高位優先法完成排序的標準爲:直到每個子序列中只有一個關鍵字爲止,所以需要分別對兩個子序列進行再分配,各自的分配表如下圖所示:

上表中,序列 1 中還有含有兩個關鍵字的子序列,所以還需要根據個位進行分配,最終按照各子序列的順序同樣會得到一個有序表。

基數排序的具體實現(採用LSD法)


具體的實現代碼爲:

如果代碼看不明白可以先看看這裏:基於基數排序實現的桶排序

public class RadixSort {

    public static void main(String[] args) {
        int[] data = {51, 944, 1, 9, 57, 366, 79, 6, 1, 345};// 待排序數組
        sort(data, 3);
        print(data);
    }

    /**
     * 從小到大排序
     * @param data 待排序數組
     * @param d 表示最大的數有多少位
     */
    public static void sort(int[] data, int d) {
        int n = 1;
        // 數組的第一維表示可能的餘數0-9
        int[][] bask = new int[10][data.length];
        // 數組index[i]用來表示該位(個、十、百.......)是 i 的數的個數
        int[] index = new int[10];
        // i:控制鍵值排序依據在哪一位(個、十、百.......)
        for (int i = 0; i < d; i++) {
            for (int j = 0; j < data.length; j++) {
                int lsd = ((data[j] / n) % 10);
                bask[lsd][index[lsd]++] = data[j];
            }
            int pos = 0;
            for (int j = 0; j < 10; j++) {
                for (int k = 0; k < index[j]; k++) {
                    data[pos++] = bask[j][k];
                }
                index[j] = 0;
            }
            n *= 10;
        }
    }

    public static void print(int array[]) {
        for (int j = 0; j < array.length; j++) {
            System.out.printf("%5d", array[j]);
        }
        System.out.println();
    }
}

基數排序的特點及性能


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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章