首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >clojure中的惯用选择排序

clojure中的惯用选择排序
EN

Stack Overflow用户
提问于 2015-06-25 12:16:09
回答 2查看 327关注 0票数 2

我试图在clojure中实现选择排序O(n2)。是的,底层排序使用非常高效的java数组排序。然而,这是一个学习练习。

下面的代码可以工作,但是我想知道是否有更惯用的方式重写它,因为下面的代码看起来很笨拙-

代码语言:javascript
复制
(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])
EN

回答 2

Stack Overflow用户

发布于 2015-06-25 21:43:31

功能解决方案可以是:

代码语言:javascript
复制
(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
EN

Stack Overflow用户

发布于 2015-06-25 19:05:44

您可以使用以下内容:

代码语言:javascript
复制
(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]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31041108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档