用于查找依赖关系的递归函数

时间:2014-12-24 05:34:24

标签: clojure

我有一组地图。给定任何地图,我想找到它依赖的所有地图。任何地图都会立即依赖。每个直接依赖项将依次具有自己的依赖关系,依此类推。

我在编写递归函数时遇到问题。下面的代码给出了stackoverflow错误。 (算法无论如何都不高效 - 我很感激帮助清理它。)

以下是我的实施 -

find-deps获取一张地图并返回一组地图:地图的直接依赖关系。

  

(find-deps [m])=> COLL

以下功能 -

  1. 检查direct-deps(即时代表)是否为空,作为基本条件。
  2. 如果没有,则会在所有直接代表上映射find-deps。这是一步 导致问题的原因。
  3. 通常在递归函数中我们能够缩小初始输入,但是在这里我的输入不断增加!

    (defn find-all-deps 
      ([m]
       (find-all-deps m []))
      ([m all-deps] 
        (let [direct-deps (find-deps m)]
          (if-not (seq direct-deps)
            all-deps
            (map #(find-all-deps % (concat all-deps %)) direct-deps)))))
    

1 个答案:

答案 0 :(得分:0)

使用有向图时,确保您不会两次访问图中的节点通常很有用。这个问题看起来很像很多图形遍历问题,而且你的解决方案非常接近正常的深度优先遍历,你只需要不遵循循环(或者不允许它们在输入中)。一种方法是在再次访问之前确保依赖关系不在图中。遗憾的是,map不太适合这种情况,因为您映射的列表中的每个元素都无法了解同一列表中其他元素的依赖关系。 reduce更适合这里,因为您正在寻找一个答案。

...
(if-not (seq direct-deps)
    all-deps
    (reduce (fn [result this-dep] 
               (if-not (contains? result this-dep)
                 (find-all-deps this-dep (conj result this-dep))
                 result)
            direct-deps
            #{})   ;; use a set to prevent duplicates.