开发者

Tree traversal with corecursion

开发者 https://www.devze.com 2023-01-08 23:55 出处:网络
I\'m trying to figure out corecursion in Clojure with nontrivial (i.e. not Fibonacci), but manageable, examples. Apparently it is possible to implement binary tree traversal with corecursion. Wikipedi

I'm trying to figure out corecursion in Clojure with nontrivial (i.e. not Fibonacci), but manageable, examples. Apparently it is possible to implement binary tree traversal with corecursion. Wikipedia has an example in Python which I am unable to understand.

开发者_StackOverflow社区How can I implement it in Clojure? Let's say I'm looking for BFS, but it could be any order.

Here's what I have so far:

(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))

Unfortunately it seems to be going all the way to the left, ignoring the right branch.


Assuming Michal's code does what you want, this also works:

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


Here is a direct translation of the bftrav Haskell function from the Wikipedia article. Note that it uses a letrec macro I've just written -- see this Gist for the latest version.

I've changed your definition of my-tree to read thus:

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

Also, my leaf? function assumes that we're only dealing with proper two-way branches and leaf nodes (so a nil on the :left branch implies a nil on the :right branch); it shouldn't be two difficult to change this to handle single-child "branches":

(defn leaf? [t] (nil? (:left t)))

The code for bftrav is as follows:

(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))

An example from the REPL:

user> (bftrav my-tree)
({:val 1, :left {:val 2, :left nil, :right nil}, :right {:val 3, :left {:val 4, :left nil, :right nil}, :right {:val 5, :left nil, :right nil}}} {:val 2, :left nil, :right nil} {:val 3, :left {:val 4, :left nil, :right nil}, :right {:val 5, :left nil, :right nil}} {:val 4, :left nil, :right nil} {:val 5, :left nil, :right nil})
user> (count (bftrav my-tree))
5
0

精彩评论

暂无评论...
验证码 换一张
取 消