Arantium Maestum

プログラミング、囲碁、読書の話題

Clojureでバケツソート

正の整数のシーケンスxsをO(n+m)時間でソートする方法としてBucket Sortがある。

0からxsの最大値mまで番号が付けられているvector of vectorを作成して、xsの全要素を一つずつ対応するvectorに入れていく。あとはconcatするだけ。

(defn bucket-sort [xs]
  (let [bucket-count (inc (apply max xs))
        buckets      (into [] (repeat bucket-count []))
        add-item     (fn [buckets item] 
                       (update-in buckets 
                                  [item] 
                                  #(conj % item)))]
    (apply concat 
           (reduce add-item buckets xs))))

xsの最大値を見つけるのにO(n)、vector of vectorを作成するのにO(m)、xsの要素一つをvectorに入れるのはindex lookupがO(1)でvector insertionもO(1)、それをn分やるのでO(n)。concatにO(n)。

O(n)のプロセスが三つとO(m)が一つ。O(n+m)で、nとmのどちらがdominateするかは状況次第。

もしmが相対的にはnに比べて小さく、そして絶対的にはメモリが許すくらいに小さいなら、非常にありがたいソート手法である。実際走らせてみると早い。