在不使用展平

时间:2015-11-10 11:21:03

标签: clojure tree max min

我需要开发一个名为bounds的函数,它将一个嵌套的数字列表作为唯一的参数(即:一棵树)。 Bounds应该返回树中最大和最小的值。例如:

(bounds '(1 (-2 17 (4) -8 (-6 13) (-8 17)))) 

使用clojure而不使用flatten函数但使用递归来访问每个节点

(defn maxv [tree]   (条件     (数字?树)树

(tree? tree)
(let [newmax (maxv (first tree)) ]                             

;;让newmax成为树中的第一个       (if(< newmax(maxv(first(rest tree)))) ;;如果树中的下一个较小             (=(newmax(maxv(first(rest tree)))))) ;;将newmax更改为此               (复发(maxv(休息树)))))
;;通过其余部分重复

这就是我的想法,我认为我也是java ish

1 个答案:

答案 0 :(得分:1)

flatten 非常高效,因此自行实施没有任何好处

如果您的嵌套列表不是太大,您可以apply (juxt min max)直接到展平列表:

(defn bounds [coll]
  (apply (juxt min max) (flatten coll)))

对于大型输入集合,我建议使用reduce代替apply

(defn bounds [coll]
  (reduce (fn [[minv maxv :as res] v]
            (if res [(min minv v) (max maxv v)] [v v]))
          nil
          (flatten coll)))

如果你真的需要纯粹的递归实现,这里有一个例子:

(defn bounds [coll]
  (loop [coll coll [minv maxv :as res] nil]
    (if-let [[h & ts] (seq coll)]
      (if (sequential? h)
          (recur (concat h ts) res)
          (recur ts (if res [(min minv h) (max maxv h)] [h h])))
      res)))

所有三个实现都会产生一个包含最小值和最大值的元组:

(bounds '(1 (-2 17 (4) -8 (-6 13) (-8 17)))) ; => [-8 17]

更新:注释sum-tree来自评论的实施

在您的代码中使用multiple recursion是一个非常糟糕的主意,因为它会非常快速地炸掉您的堆栈:

(sum-tree (range 7000)) ; => java.lang.StackOverflowError

尝试使用tail recursionrecurhigher-order functions代替:

(defn sum-tree [tree]
  (if (number? tree)
      tree
      (reduce + (map sum-tree tree))))