【问题标题】:Find all paths from root to leaves of tree in Scheme在Scheme中查找从树根到叶子的所有路径
【发布时间】:2010-06-28 05:28:27
【问题描述】:

给定一棵树,我想找到从根到每片叶子的路径。

所以,对于这棵树:

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

这比我原来的要整洁得多。

【问题讨论】:

    标签: lisp scheme racket


    【解决方案1】:

    我的 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))
    

    【讨论】:

    • 这更简洁一些 - 并且可能更正确,因为它处理具有单个节点的树的方式: (paths 'a) => ((a)), 而 (g ' a) => (a)。 CL的mapcan或多或少等同于我上面的map2吗?你知道内置的 Scheme 函数吗?
    • 我对Scheme了解不多,但我猜想mapcan之类的东西是可用的。不过,也许它被认为实施起来很简单。你的map2 原则上看起来是等价的,但是它有错误的尾调用,所以当列表太长时它会爆栈。也许你应该使用累加器/反向成语。
    • 方案相当于mapcan 是来自SRFI-1 的append-map
    【解决方案2】:

    Svante 答案的 R5RS 翻译:

    (定义(累积操作初始化序列) (定义(iter ans rest) (如果(空?休息) 回答 (iter (op ans (car rest)) (cdr休息)))) (迭代初始化序列)) (定义(展平序列) (累积追加'() seq)) (定义(平面图操作序列) (展平(map op seq))) (定义(原子?x) (不是(对?x))) (定义(路径树) (如果(原子?树) (列表(列表树)) (平面图(lambda(节点) (地图(lambda(路径) (缺点(汽车树)路径)) (路径节点))) (cdr 树))))

    【讨论】:

      【解决方案3】:

      我认为您可以将示例树定义为(从左到右)每个列表。因此,您的示例树将是: (D (B (A () (C () (F () G ) ) ) E) () ) 并且更容易遍历

      【讨论】:

      • 我认为你误读了我的图表 - A 是树的根。另外(这可能从问题中不清楚)一个节点可以有两个以上的分支,所以我认为你的方法行不通。
      • 我刚刚意识到我误读了您的图表。我会说如果 g 函数有效,你应该使用它:-)
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2011-10-31
        • 1970-01-01
        • 1970-01-01
        • 2015-10-03
        • 1970-01-01
        • 2018-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多