从Clojure中的列表创建树

时间:2016-02-03 13:05:57

标签: list clojure tree

您好我是Clojure的新手,

我正在尝试解决以下问题1

我解决这个问题的第一步是编写一个接收列表的函数(在我的例子中,是地名)并将其转换为树。

(list 'Karlsruhe 'Stuttgart '100 'Stuttgart 'Ulm '80 'Ulm 'Muenchen '120)

我希望树看起来像这样:2

我希望树看起来像这样的原因是,我打算编写一个接收目标和目的地的函数,在新创建的树中搜索目标,记录所有右手节点,然后在最后,检查哪个是最小的并返回。

我想要一些帮助/指导谢谢。

微米。

1 个答案:

答案 0 :(得分:1)

你要做的事情可以在不构建树的情况下完美地完成。您的列表中有三元组,包含源,目的地和一些数字。所以我会在这里制作source[destination number]的地图,以便更好地查找,然后以递归方式遍历它:

(def items (list 'Karlsruhe 'Stuttgart '100 
                 'Stuttgart 'Ulm '80 
                 'Ulm 'Muenchen '120))

(def items-lookup-map (into {} 
                        (map (juxt first rest) 
                             (partition 3 items)))

现在您的查找地图如下所示:

{Karlsruhe (Stuttgart 100), 
 Stuttgart (Ulm 80), 
 Ulm (Muenchen 120)}

现在您可以轻松编写一个函数来查找从源到目标的路径:

(defn find-path [source dest lookup-map]
  (let [[prev [dest & _]] (split-with
                           #(and (not (nil? %)) (not= % dest))
                           (iterate #(first (lookup-map %))
                                    source))]
    (when dest (concat prev [dest]))))

让我们测试一下:

user> (find-path 'Karlsruhe 'Ulm items-lookup-map)
(Karlsruhe Stuttgart Ulm)
user> (find-path 'Karlsruhe 'Prague items-lookup-map)
nil
user> (find-path 'Moscau 'Ulm items-lookup-map)
nil

现在您可以随意使用它,例如在路径中找到最小数字:

(defn min-distance [src dest lookup-map]
  (when-let [path (seq (find-path src dest lookup-map))]
    (apply min (map #(second (lookup-map %)) (butlast path)))))

user> (min-distance 'Karlsruhe 'Muenchen items-lookup-map)
80