【问题标题】:Clojure - sort functionClojure - 排序功能
【发布时间】:2014-10-30 00:07:40
【问题描述】:

我正在尝试编写一个递归排序函数,将列表从低到高排序(duh)。我目前正在获得输出,只是不是正确的输出。这是我的代码:

(defn sort/predicate [pred loi]
   (if (empty? loi)
     ()
     (if (= (count loi) 1)
       (cons (first loi) (sort pred (rest loi)))
       (if (pred (first loi) (first (rest loi)))
         (cons (first loi) (sort pred (rest loi)))
         (if (pred (first (rest loi)) (first loi))
           (cons (first (rest loi)) (sort pred (cons (first loi) (rest (rest loi)))))
           (cons (first loi) (sort pred (rest loi))))))))

基本上,我比较列表中的前两个元素,如果第一个元素更小,我会将其与比较列表中接下来的两个元素的结果进行比较。如果列表的第二个元素更小,我将第二个元素与第一个元素的前两个元素以及第二个元素之后的所有内容排序的结果相结合(抱歉,如果这很难理解)。然后,当列表中只剩下一个元素时,我将它扔到最后并返回它。但是,在某个地方存在一个错误,因为我应该得到以下信息:

>(sort/predicate < '(8 2 5 2 3))
(2 2 3 5 8)

但相反,我得到:

>(sort/predicate < '(8 2 5 2 3))
(2 5 2 3 8)

我对 clojure 很陌生,因此非常感谢任何帮助。另外,我想保持我的代码大致相同(我不想使用已经存在的排序函数)。谢谢

【问题讨论】:

  • 我刚刚意识到我只比较前两个元素。

标签: clojure


【解决方案1】:

clojure.core/sort用Java实现更通用。

user=> (sort '(8 2 5 2 3))
(2 2 3 5 8)
user=> (sort > '(8 2 5 2 3))
(8 5 3 2 2)
user=> (source sort)
(defn sort
  "Returns a sorted sequence of the items in coll. If no comparator is
  supplied, uses compare.  comparator must implement
  java.util.Comparator.  If coll is a Java array, it will be modified.
  To avoid this, sort a copy of the array."
  {:added "1.0"
   :static true}
  ([coll]
   (sort compare coll))
  ([^java.util.Comparator comp coll]
   (if (seq coll)
     (let [a (to-array coll)]
       (. java.util.Arrays (sort a comp))
       (seq a))
     ())))
nil
user=> 

【讨论】:

    【解决方案2】:

    我不认为这是一种非常有效的排序方式,但我尽量忠实于您的意图:

    (defn my-sort [cmp-fn [x & xs]]
      (cond
        (nil? x) '()
        (empty? xs) (list x)
        :else (let [[y & ys :as s] (my-sort cmp-fn xs)]
                (if (cmp-fn x y)
                  (cons x s)
                  (cons y (my-sort cmp-fn (cons x ys)))))))
    

    【讨论】:

    • 你说得对,效率不高。我从头开始,并且能够制作一个效果很好的合并排序函数。
    • @ChrisPhillips 不要让多余的问题悬而未决。如果您有自己的好答案,请提交并接受。即使您的插入已在此处修复,这与进行合并一样麻烦,正如您所发现的那样,合并是更快更简单算法的基础。您可以相应地注释问题。
    【解决方案3】:

    ;;合并排序实现——不消耗堆栈的递归排序

    (defn merge-sort
      ([v comp-fn]
       (if (< (count v) 2) v
         (let [[left right] (split-at (quot (count v) 2) v)]
           (loop [result       []
                  sorted-left  (merge-sort left comp-fn)
                  sorted-right (merge-sort right comp-fn)]
             (cond
               (empty? sorted-left) (into result sorted-right)
               (empty? sorted-right) (into result sorted-left)
               :else (if (comp-fn 0 (compare (first sorted-left) (first sorted-right)))
                       (recur (conj result (first sorted-left)) (rest sorted-left) sorted-right)
                       (recur (conj  result (first sorted-right))  sorted-left (rest sorted-right))))))))
      ([v] (merge-sort v >)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-29
      • 2015-12-22
      • 2018-10-29
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2021-12-23
      相关资源
      最近更新 更多