分配排序之基數排序(Java語言描述)

分配排序之基數排序

基數排序是在計數排序上的應用擴展,是分配排序的一個特例,我們已經知道計數排序(桶排序)適用於小數範圍內的排序,對於大數則效率不高,而今天要說的基數排序,利用了進制基數的特點,將大數拆解爲進制內範圍的小數,多次執行計數或其他穩定排序,實現了大數範圍內的排序功能。

例如對於兩位數之間的排序問題,我們一般從十位開始比較,十位相同的數,再比較個位,最終得出想要的結果,基數排序的過程大致如此,不同之處在於對於十位或個位相同的數,我們採用計數排序的處理,中間不需要進行元素之間的比較。

基數排序分爲高位優先法(most significant digit first, MSD)與低位優先法(least significant digit first, LSD),計算機在實現高位優先法時,需要進行嵌套分配桶空間,是一個遞歸分治的算法,執行起來比較複雜,因此LSD的實現則更爲常見。

LSD基於數組的實現代碼如下:

import java.util.Arrays;

public class RadixSort {

    public static void main(String[] args) {
        int[] arr = new int[] { 97, 53, 88, 59, 26, 41, 88, 31, 22 };
        arr = radixSort(arr, 9, 2, 10);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 
     * @param array 排序序列
     * @param n     排序序列元素數
     * @param d     排序位數(兩位數傳入2)
     * @param r     基
     */
    public static int[] radixSort(int[] array, int n, int d, int r) {
        // 內部桶排序時用以保存各桶中的元素數
        int[] count = new int[r];
        // 按照不同基位進行桶排序時存放元素
        int[] tmpArray = new int[n];
        // 模除數,計算桶位
        int radix = 1;

        // 臨時變量,用於計算每個元素的桶位,避免重複聲明
        int k = 0;

        // 進行d輪計數排序(/桶排序)
        for (int i = 0; i < d; i++) {
            // 每輪循環,須重新初始化count數組
            for (int j = 0; j < r; j++) {
                count[j] = 0;
            }

            // 遍歷原始數組,計算每個桶位的元素數,存儲於count數組
            for (int j = 0; j < n; j++) {
                k = (array[j] / radix) % r;
                count[k]++;
            }
            // 計數器對應位數值修改爲下一位的開始位置
            for (int j = 1; j < r; j++) {
                count[j] = count[j] + count[j - 1];
            }
            
            // 進行桶排序過程
            for (int j = n - 1; j >= 0; j--) {
                // 計算元素桶位
                k = (array[j] / radix) % r;
                count[k]--;
                tmpArray[count[k]] = array[j];
            }
            
            // 回寫到原數組
            for (int j = 0; j < n; j++) {
                array[j] = tmpArray[j];
            }

            // 基位遞增
            radix *= r;
        }
        return array;
    }
}

小結

基數排序的主要思想是按照基數對排序元素進行拆分,拆分後的每個值都屬於進制內的數值,在此基礎上,按照每一位進行桶排序,與直觀的理解不同,由於計算機在處理遞歸分治算法時較爲複雜,因此一般實現方式是LSD–低位優先的算法,稍微考慮下,高位優先MSD與低位LSD之間的直觀區別僅僅是排序時處理的方向不一樣。

推薦資料:
Radix sort - Wikiwand

歡迎關注我的公衆號,瞭解更多內容:
我的公衆號

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