Stumped with functional breadth-first tree traversal in Clojure?

前端 未结 4 1111
借酒劲吻你
借酒劲吻你 2021-02-02 12:24

Say I have a tree defined as per the recommendation in this post, although it\'s a vector in my case, which hopefully shouldn\'t matter (they\'re vectors in Programming Clojure

相关标签:
4条回答
  • 2021-02-02 12:41

    Your tree data is incorrect. It should be [1 [2 [4] [5]] [3 [6]]]

    Also, you're mixing the tree traversal with printing and building up a result. Things get simpler if you concentrate on doing the hard part separately:

    (def tree [1 [2 [4] [5]] [3 [6]]])
    

    NOTE THIS IS DEPTH-FIRST. SEE BELOW

    (defn bf "return elements in tree, breath-first"
       [[el left right]] ;; a tree is a seq of one element,
                         ;; followed by left and right child trees
       (if el
         (concat [el] (bf left) (bf right))))
    
    (bf tree)
    => (1 2 4 5 3 6)
    

    CORRECT VERSION

    (defn bf [& roots] 
       (if (seq roots) 
           (concat (map first roots) ;; values in roots
                   (apply bf (mapcat rest roots))))) ;; recursively for children
    
    (bf tree)
    => (1 2 3 4 5 6)
    
    0 讨论(0)
  • 2021-02-02 12:43

    many combinations of reduceand conj can be replaced with single into call in the case above with reduce you may need to pass an initial empty vector to reduce to get make conjunction happy.

    0 讨论(0)
  • 2021-02-02 12:44

    This might help, I was creating an algorithm to evaluate if a tree is symmetric and used a breadth-first traversal:

    (defn node-values [nodes]
        (map first nodes))
    
    (defn node-children [nodes]
      (mapcat next nodes))
    
    (defn depth-traversal [nodes]
        (if (not (empty? nodes))
            (cons (node-values nodes) (depth-traversal (node-children nodes)))))
    
    (defn tree-symmetric? [tree]
        (every?
            (fn [depth] (= depth (reverse depth)))
            (depth-traversal (list tree))))
    
    (def tree '(1 (2 (3) (4)) (2 (4) (3))))
    (node-values (list tree)) ; (1)
    (node-children (list tree)) ; ((2 (3) (4)) (2 (4) (3)))
    (depth-traversal (list tree)) ; ((1) (2 2) (3 4 4 3))
    (tree-symmetric? tree) ; true
    
    0 讨论(0)
  • 2021-02-02 12:53

    Since apparently there is still no breadth-first solution posted, here is a simple algorithm, implemented first eagerly, and then transformed to be lazy:

    (defn bfs-eager [tree]
      (loop [ret [], queue (conj clojure.lang.PersistentQueue/EMPTY tree)]
        (if (seq queue)
          (let [[node & children] (peek queue)]
            (recur (conj ret node) (into (pop queue) children)))
          ret)))
    
    (defn bfs-lazy [tree]
      ((fn step [queue]
         (lazy-seq
          (when (seq queue)
            (let [[node & children] (peek queue)]
              (cons node
                    (step (into (pop queue) children)))))))
       (conj clojure.lang.PersistentQueue/EMPTY tree)))
    
    0 讨论(0)
提交回复
热议问题