我试图在clojure中实现选择排序O(n2)。是的,底层排序使用非常有效的java的数组排序。然而,这是一项学习练习。
下面的代码有效,但是我想知道是否有一种更惯用的重写方式,因为下面看起来很笨重 -
(defn mins [coll]
(reduce (fn[[min-coll rest-coll] val]
(case (compare val (first min-coll))
-1 [[val] (apply conj rest-coll min-coll)]
0 [(conj min-coll val) rest-coll]
1 [min-coll (conj rest-coll val)]))
[[(first coll)] []]
(rest coll)))
;; (mins [3 1 1 2]) => [[1 1] [3 2]]
(defn selection-sort [coll]
(loop [[sorted coll] [[] coll]]
(let [[s c] (mins coll)]
(if-not (seq coll)
sorted
(recur [(concat sorted s) c])))))
(selection-sort [3 1 1 2 5 7 8 8 4 6])
答案 0 :(得分:1)
功能性解决方案可能是:
(defn selection-sort
[input]
(let [ixs (vec (range (count input)))
min-key-from (fn [acc ix] (apply min-key acc (subvec ixs ix)))
swap (fn [coll i j] (assoc coll i (coll j) j (coll i)))]
(reduce
(fn [acc ix] (swap acc ix (min-key-from acc ix))) input ixs)))
答案 1 :(得分:0)
您可以使用以下内容:
(defn remove-first [coll e]
(if-let [pos (and (seq coll) (.indexOf coll e))]
(vec (concat
(subvec coll 0 pos)
(subvec coll (inc pos))))
coll))
(defn best [coll f]
(reduce f
(first coll)
(rest coll)))
(defn select-sort
([coll] (select-sort coll min))
([coll fmin]
(loop [sorted (transient []) c (vec coll)]
(if (seq c)
(let [n (best c fmin)]
(recur (conj! sorted n) (remove-first c n)))
(persistent! sorted)))))
=> (select-sort [3 5 2])
=> [2 3 5]
=> (select-sort [3 5 2] max)
=> [5 3 2]