基數排序是一種非比較型整數排序算法,它通過按數位從低位到高位依次處理數字,將每個數字根據當前數位的數值分配到不同的“桶”中,再按桶的順序收集回原數組,重複這一過程直到所有數位處理完畢。這種方法特別適合處理位數較少的整數,效率較高。

基數排序的基本思想

  1. 分配:按當前數位(如個位、十位、百位)將數字分配到對應的桶中。例如,個位數字爲3的數放入桶3,十位數字爲2的數放入桶2等。
  2. 收集:按桶的順序(0到9)依次取出桶中的數字,放回原數組,完成一次數位的排序。
  3. 重複:對每一個數位(從低位到高位)重複上述分配和收集過程,直到所有數位處理完畢。

舉例說明排序過程

以數組 [5, 3, 8, 12, 23, 100] 爲例,逐步演示排序過程:

初始數組

[5, 3, 8, 12, 23, 100]

第一輪:處理個位(radix=1)

每個數的個位數字爲:5(個位5)、3(個位3)、8(個位8)、12(個位2)、23(個位3)、100(個位0)。
- 分配到桶中:
桶0:[100],桶2:[12],桶3:[3, 23],桶5:[5],桶8:[8],其他桶空。
- 收集回數組:[100, 12, 3, 23, 5, 8]

第二輪:處理十位(radix=10)

每個數的十位數字爲:100(十位0)、12(十位1)、3(十位0)、23(十位2)、5(十位0)、8(十位0)。
- 分配到桶中:
桶0:[100, 3, 5, 8],桶1:[12],桶2:[23],其他桶空。
- 收集回數組:[100, 3, 5, 8, 12, 23]

第三輪:處理百位(radix=100)

每個數的百位數字爲:100(百位1)、3(百位0)、5(百位0)、8(百位0)、12(百位0)、23(百位0)。
- 分配到桶中:
桶0:[3, 5, 8, 12, 23],桶1:[100],其他桶空。
- 收集回數組:[3, 5, 8, 12, 23, 100]

排序完成!

Java代碼實現

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

public class RadixSort {

    public static void radixSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return; // 空數組直接返回
        }

        // 1. 找到數組中的最大數,確定最大數位
        int max = arr[0];
        for (int num : arr) {
            if (num > max) {
                max = num;
            }
        }

        // 2. 按數位從低位到高位處理(個位、十位、百位...)
        for (int radix = 1; max / radix > 0; radix *= 10) {
            // 創建10個桶(0-9),用ArrayList動態存儲元素
            List<List<Integer>> buckets = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                buckets.add(new ArrayList<>());
            }

            // 3. 分配:將每個數按當前位數字放入對應桶
            for (int num : arr) {
                int currentDigit = (num / radix) % 10; // 獲取當前位數字
                buckets.get(currentDigit).add(num);
            }

            // 4. 收集:按桶順序(0-9)放回原數組
            int index = 0;
            for (List<Integer> bucket : buckets) {
                for (int num : bucket) {
                    arr[index++] = num;
                }
            }
        }
    }

    // 測試代碼
    public static void main(String[] args) {
        int[] arr = {5, 3, 8, 12, 23, 100};
        System.out.println("排序前:" + java.util.Arrays.toString(arr));
        radixSort(arr);
        System.out.println("排序後:" + java.util.Arrays.toString(arr));
    }
}

代碼關鍵點解析

  1. 找到最大數:確定需要處理的最高數位(如最大數爲100時,需處理百位)。
  2. 獲取當前位:通過 (num / radix) % 10 計算當前數位。例如:
    - 個位:radix=1(num / 1) % 10 → 直接取個位。
    - 十位:radix=10(num / 10) % 10 → 取十位。
  3. 桶的分配與收集:使用 ArrayList 動態存儲每個桶的元素,避免預先確定桶容量,收集時按順序放回原數組。

時間與空間複雜度

  • 時間複雜度O(d*(n+k)),其中 d 是最大數的位數,n 是數組長度,k 是基數(此處 k=10)。若 dk 固定,時間複雜度近似 O(n)
  • 空間複雜度O(n+k),需 n 個空間存儲數組,k 個桶。

總結

基數排序通過“按位分配-收集”的方式實現排序,適合整數排序,尤其當數字位數較少時效率較高。代碼中使用 ArrayList 作爲桶,簡化了動態存儲過程,且保持了排序的穩定性(相同數字相對順序不變)。對於負數,可先分離正負再分別排序,最後合併。

小夜