在Scheme中查找从树根到树叶的所有路径

时间:2010-06-10 23:25:24

标签: lisp scheme racket

鉴于树,我想找到从根到每片叶子的路径。

所以,对于这棵树:

    D
   /
  B
 / \ 
A   E
 \
  C-F-G

具有从根(A)到叶(D,E,G)的以下路径:

(A B D), (A B E), (A C F G)

如果我将上面的树表示为(A (B D E) (C (F G))),那么函数g可以解决问题:

(define (paths tree)
  (cond ((empty? tree)
         '())
        ((pair? tree)
         (map (lambda (path)
                (if (pair? path)
                    (cons (car tree) path)
                    (cons (car tree) (list path))))
              (map2 paths (cdr tree))))
        (else
         (list tree))))

(define (map2 fn lst)
  (if (empty? lst)
      '()
      (append (fn (car lst))
              (map2 fn (cdr lst)))))

但这看起来完全错了。我暂时没有做过这种想法,但我觉得应该有一种更简洁的方法。任何有关更好解决方案(使用任何语言)的想法都将受到赞赏。


编辑 - 将Svante的解决方案映射到Scheme中:

(define (paths tree)
  (if (pair? tree)
      (append-map (lambda (node)
              (map (lambda (path)
                     (cons (car tree) path))
                   (paths node)))
            (cdr tree))
      (list (list tree))))

比我原来的要整洁得多。

4 个答案:

答案 0 :(得分:3)

我对Common Lisp更加流利。

(defun paths (tree)
  (if (atom tree)
      (list (list tree))
      (mapcan (lambda (node)
                (mapcar (lambda (path)
                          (cons (car tree) path))
                        (paths node)))
              (cdr tree))))

CL-USER> (paths '(A (B D E) (C (F G))))
((A B D) (A B E) (A C F G))

答案 1 :(得分:2)

Svante答案的R5RS翻译:

(define (accumulate op init seq)
  (define (iter ans rest)
    (if (null? rest)
        ans
        (iter (op ans (car rest))
              (cdr rest))))
  (iter init seq))

(define (flatten seq)
  (accumulate append '() seq))

(define (flatmap op seq)
  (flatten (map op seq)))

(define (atom? x)
  (not (pair? x)))

(define (paths tree)
  (if (atom? tree)
      (list (list tree))
      (flatmap (lambda (node)
                 (map (lambda (path)
                        (cons (car tree) path))
                      (paths node)))
               (cdr tree))))

答案 2 :(得分:0)

我认为您可以将示例树定义为(根左)每个列表。所以你的例子树将是:(D(B(A()(C()(F()G)))E)()),这更容易遍历

答案 3 :(得分:0)

您需要树搜索算法。广度优先或深度优先遍历都可以工作,并且在这种情况下没有区别,因为您需要爬行整个树。每当你到达一片叶子时,只需在结果中存储当前路径。