Clojure中的基本树递归

时间:2015-11-12 19:25:10

标签: clojure tree

我想知道是否有人可以帮助我,因为我已经使用此代码打了一个块。我的代码如下所示。

当我运行跟踪时,它会在达到零值时一直停止,是否有人知道出了什么问题?

这是我的数据:

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

代码:

(defn tree? [t]
  (and (seq t) (not (empty? t))))

(defn bounds2
  ([tree] (bounds2 tree 99 -99))
  ([tree minVal maxVal]
   (cond
     (number? tree) tree
     (tree? tree)
     (cond

       (nil? (bounds2 (first tree) minVal maxVal))
       (bounds2 (rest tree) minVal maxVal)

       ((complement nil?) (bounds2 (first tree) minVal maxVal))
       (cond
         (< (bounds2 (first tree) minVal maxVal) minVal)
         (recur (rest tree) (first tree) maxVal)

         (> (bounds2 (first tree) minVal maxVal) maxVal)
         (recur (rest tree) minVal (first tree)))

       (empty? tree) nil))))

1 个答案:

答案 0 :(得分:0)

这里有几个问题。最直接的一个是你永远不会实际返回任何界限。 cond语句中的每个可能的退出点都是各种未修改的递归调用,数字或nil。从逻辑上讲,您需要在某些时候返回类似[minVal maxVal]的内容,并且您应该期望所有递归调用都返回该格式的内容。当然,这会使你的比较逻辑变得相当复杂。

其他重要的一点包括tree?在逻辑上等同于seq(正如评论中指出的那样),而你的(empty? tree)子句是死代码,因为{{1}绝不能同时满足tree = tree?seq。 (事实证明,empty?仍会返回(bounds2 '()),但这是因为nil如果您没有匹配任何子句就会返回cond。)

如果您原谅完全重写,我认为这可以满足您的需求,与原始代码完全相同。 (您在评论中提到您不想使用nil,因此我避免使用它和中间flatten解决方案。)

reduce

我的大多数变化都是文体的(使用(defn bounds2 [tree] (loop [[x & more :as tree] tree, minVal 99, maxVal -99] (cond (empty? tree) [minVal maxVal] (number? x) (recur more (min x minVal) (max x maxVal)) (seq x) (recur (concat x more) minVal maxVal)))) 而不是多个arities;解构;取消嵌套loop语句);这里逻辑的一个主要变化是我们正在使用cond到“concat”。同样重要的是要注意,对我们的所有递归调用使用flatten将有助于保护我们免于破坏堆栈。