【排序算法】- 基數排序

排序動圖

排序思路

將數組按基數進行排序,個位,十位,百位…

排序流程

  • 取數組中最大的數,並計算位數
  • 從最低位開始取每個位的數組成一個新的數組
  • 對新的數組重新按位排序,直到位數排完

代碼實現

public static void radixSort(int[] arr) {
    // 找出最大的數
    int max = Integer.MIN_VALUE;
    for (int i = 0; i < arr.length; i ++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    // 計算最大的數有幾位
    int length = (max+"").length();
    // 存放每次排序後的數字
    int[] temp = arr;
    // temp 數組的下標
    int index = 0;
    // 排序 length 次 n 代表每次的需要取模的值
    for (int i = 0, n = 1; i < length; i++, n*=10) {
        // 存放每個位置對應的數
        int[][] bucket = new int[10][arr.length];
        // 存放每個下標放了一個數字
        int[] counts = new int[10];
        // 排序
        for (int j = 0; j < arr.length; j++) {
            // 取模放入對應的數組中
            int indexVal = temp[j] / n % 10;
            bucket[indexVal][counts[indexVal]] = temp[j];
            counts[indexVal] = ++counts[indexVal];
        }
        // 將每個下標的數字按順序取出來
        for (int k = 0; k < 10; k++) {
            for (int l = 0; l < counts[k]; l++) {
                temp[index] = bucket[k][l];
                index++;
            }
        }
        // index 歸 0
        index = 0;
    }
    // 將臨時數組賦予真實數組
    for (int i = 0; i < arr.length; i++) {
        arr[i] = temp[i];
    }
}

代碼優化 - 使用隊列記錄數組

  • 自定義隊列 MyQueue.java
public class MyQueue {

    /**
     * 使用數組作爲隊列的底層
     */
    private int[] arr;

    /**
     * 構造方法
     */
    public MyQueue() {
        arr = new int[0];
    }

    /**
     * 入隊
     *
     * @param e 入隊的元素
     */
    public void add(int e) {
        // 創建一個新的數組
        int[] newArray = new int[arr.length + 1];
        // 將數據複製到新數組
        for (int i = 0; i < arr.length; i++) {
            newArray[i] = arr[i];
        }
        // 入隊
        newArray[arr.length] = e;
        // 將新數組賦值給原來的數組
        arr = newArray;
    }

    /**
     * 出隊
     *
     * @return 出隊的元素
     */
    public int poll() {
        // 隊列是否爲空
        if (isEmpty()) {
            throw new RuntimeException("Queue is Empty");
        }
        // 記錄出隊的元素
        int e = arr[0];
        // 創建一個新的數組
        int[] newArray = new int[arr.length-1];
        // 將數據複製到新數組
        for (int i = 0; i < newArray.length; i++) {
            newArray[i] = arr[i+1];
        }
        // 將新數組賦值給原來的數組
        arr = newArray;
        // 返回出隊的元素
        return e;
    }

    /**
     * 隊列是否爲空
     *
     * @return true/false
     */
    public boolean isEmpty() {
        return arr.length == 0;
    }
}
  • 使用隊列優化技術排序 RadixQueueSort.java
public class RadixQueueSort {
    public static void main(String[] args) {
        int[] arr = new int[]{54, 4, 36, 125, 435, 52, 23, 678, 34, 12, 879};
        radixQueueSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 使用隊列實現基數排序
     *
     * @param arr 數組
     */
    public static void radixQueueSort(int[] arr) {
        // 定義最大值,找出最大的數
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < arr.length; i++) {
            if (max < arr[i]) {
                max = arr[i];
            }
        }
        // 計算最大值的位數
        int length = (max + "").length();
        // 定義一個記錄數字的隊列數組 0 1 2 3 4 ...
        MyQueue[] myQueue = new MyQueue[10];
        // 爲每個隊列初始化
        for (int i = 0; i < myQueue.length; i++) {
            myQueue[i] = new MyQueue();
        }
        // 定義一個記錄排序好的數組
        int[] temp = arr;
        // 記錄臨時數組的下標
        int index = 0;
        // 循環基數排序
        for (int i = 0, n = 1; i < length; i++, n *= 10) {
            // 遍歷所有數據
            for (int j = 0; j < temp.length; j++) {
                // 計算餘數
                int indexVal = temp[j] / n % 10;
                // 加入對應餘數的隊列
                myQueue[indexVal].add(temp[j]);
            }
            // 取出隊列中的數據
            for (int k = 0; k < myQueue.length; k++) {
                while (!myQueue[k].isEmpty()) {
                    temp[index] = myQueue[k].poll();
                    index++;
                }
            }
            // 將 index 初始爲 0
            index = 0;
        }
        // 將臨時數組賦值給原來的數組
        for (int i = 0; i < arr.length; i++) {
            arr[i] = temp[i];
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章