树遍历与corecursion

时间:2010-07-22 19:26:59

标签: algorithm clojure

我试图用非平凡的(即不是斐波那契)来解决Clojure中的核心运行,但是可以管理的例子。显然,可以使用corecursion实现二叉树遍历。维基百科在Python中有一个我无法理解的例子。

如何在Clojure中实现它?假设我正在寻找BFS,但它可能是任何订单。

这是我到目前为止所拥有的:

(defstruct tree :val :left :right)

(def my-tree (struct tree 1 (struct tree 2) (struct tree 3 4 5)))

(def bfs (lazy-cat [my-tree] (map #(:left %) bfs) (map #(:right %) bfs) ))

(println (take 4 bfs))

不幸的是,它似乎一路向左,忽略了正确的分支。

2 个答案:

答案 0 :(得分:8)

假设Michal的代码符合您的要求,这也有效:

(defn bftrav [& trees]
  (when trees
    (concat trees 
      (->> trees
        (mapcat #(vector (:left %) (:right%)))
        (filter identity)
        (apply bftrav)))))

答案 1 :(得分:2)

以下是维基百科文章中bftrav Haskell函数的直接翻译。请注意,它使用我刚刚撰写的letrec宏 - 请参阅this Gist了解最新版本。

我已将my-tree的定义更改为:

(def my-tree (struct tree 1 (struct tree 2) (struct tree 3 (struct tree 4) (struct tree 5))))

此外,我的leaf?函数假设我们只处理正确的双向分支和叶节点(因此nil分支上的:left意味着{{1}在nil分支上);改变这一点来处理单子“分支”应该不难两个:

:right

(defn leaf? [t] (nil? (:left t))) 的代码如下:

bftrav

REPL的一个例子:

(defn bftrav [t]
  (letrec [queue (lazy-seq (cons t (trav 1 queue)))
           trav (fn [l q]
                  (lazy-seq
                    (cond (zero? l) nil
                          (leaf? (first q)) (trav (dec l) (rest q))
                          :else (let [{:keys [left right]} (first q)]
                                  (cons left (cons right (trav (inc l) (rest q))))))))]
    queue))