バケットソート習作
(defun max-elements (&optional (list) (elm 0)) (if (not list) elm (max-elements (cdr list) (if (> elm (car list)) elm (car list))))) (defun vector-to-list (&optional (array) (num 0)) (if (< num (length array)) (let ((anum (svref array num))) (cond ((= 0 anum) (vector-to-list array (1+ num))) ((< 1 anum) (progn (setf (svref array num) (1- anum)) (cons (1+ num) (vector-to-list array num)))) (t (cons (1+ num) (vector-to-list array (1+ num)))))))) (defun list-to-vector (list array) (if list (progn (setf (svref array (1- (car list))) 1) (list-to-vector (cdr list) array)) array)) (defun bucket-sort (list) (setf ary (make-array (list (max-elements list)) :initial-element 0)) (vector-to-list (list-to-vector list ary))) ; 結果 ; * (bucket-sort '(11 8 10 13 4 15 1 12 2)) ; ; (1 2 4 8 10 11 12 13 15) ; *
これまで書いたソートアルゴリズムを見れば分かるけど、極力vector mapは使わず、Lisp特有のプリミティブな処理で表現しようと努力してきた。が、このアルゴリズムは配列の要素番号がキモなので、やむなくvector mapを採用することに。
あ、でも、もうちょっと頑張れば、これも単方向リストのみで表現できるかも。
(追記)
いや、やっぱ俺の技量だと相当頑張る必要があるので、時間的制約から、とりあえずここで止める。
(追記 3/25)
要素が重複している時に対応できるようにした。