Stan Blog

學習過程中的一些記錄

[Algorithm] Radix Sort (基數排序)

基數排序(英語:Radix sort),屬於「分配式排序」(distribution sort),是一種非比較型整數排序演算法

基數排序法會使用到「桶子」(bucket),屬於穩定性的排序(stable sort)

依比較的方向可分為 MSD (Most Significant Digit First) 和 LSD (Least Significant Digit First) 兩種。MSD 從最高有效鍵值開始排序(最大位數排到小),而 LSD 則是從最低有效鍵值開始排序(最小位數排到大)

Radix Sort 的定義 (參考維基百科)

原理是將整數按位元數切割成不同的數字,然後按每個位數分別比較。

由於整數也可以表達字串(比如名字或日期)和特定格式的浮點數

所以基數排序也不是只能使用於整數

主要步驟

  1. 取得每個資料鍵值的最 小/大 位數

  2. 依據該位數大小排序資料

  3. 取得下一個有效位數,並重複步驟二,至最 小/大 位數為止

可參考維基上動圖

維基百科 - 基數排序動圖

時間複雜度 O(k.n)

範例程式碼

Ruby 範例

附上 Ruby 的 online sandbox,有興趣可以把 code 貼進去玩玩看

arr = 20.times.map{ rand 100 }

def radix_sort(array)
    # 找出 array 裡的最大長度
    max_length = Math.log(array.max(), 10).ceil
    max_length.times do |j|
        # 建立 buckets
        buckets = (0..9).map{ [] }
        array.each do |i|
          # 取 i 的個位數數字,並將值塞進對應的 bucket
            buckets[i.to_s[-j - 1].to_i] << i
        end
        # 排除空 bucket,並做排序
        array = buckets.select{ |i| !i.empty? }.reduce(:+)
    end
    array
end

puts 'before'
puts arr.inspect
puts
puts 'after'
puts radix_sort(arr).inspect

結果如下

螢幕快照 2020-11-17 14 04 51

JavaScript 範例

JavaScript 的 online sandbox,有興趣可以把 code 貼進去玩玩看

const unsortedArr = [5, 41, 41, 56, 6, 63, 91, 69, 96, 96, 89, 32, 69, 67, 86, 52, 49, 19, 8, 91];

radixSort = arr => {
  // 找出 array 裡的最大長度
    const maxNum = Math.max(...arr);
    for (let i = 0; i < maxNum; i++) {
    // 建立 buckets
        let buckets = Array.from({length:10}, () => [])
        for (let j = 0; j < arr.length; j++) {
      // 取 arr[j] 的個位數數字,並將值塞進對應的 bucket
            buckets[getPosition(arr[j], i)].push(arr[j])
        }
        arr= [].concat(...buckets)
    }
    return arr
}

getPosition = (num, place) => Math.floor(num / Math.pow(10, place)) % 10;

console.log(radixSort(unsortedArr));

結果如下

螢幕快照 2020-11-17 14 09 27

Comments

comments powered by Disqus