【问题标题】:How to form tree into individual paths leading to each leaf如何将树形成通向每片叶子的单独路径
【发布时间】:2013-01-03 20:07:23
【问题描述】:

我有一棵树:

(A . ((C . ((D . nil)(E . nil)))
      (B . ((F . nil)(G . nil)))))

我想把这棵树变成:

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

我已经为此实现了这个功能:

(defun tree->paths (tree &optional buff)
  (labels ((recurse (follow-ups extended-list)
             (if follow-ups
                 (append (list (tree->paths (car follow-ups) extended-list))
                         (recurse (cdr follow-ups) extended-list))
               nil)))
    (rstyu:aif (cdr tree)
               (recurse it (append buff (list (car tree))))
               (append buff (list (car tree))))))

但应用它会导致:

(tree->paths '(A . ((C . ((D . nil) (E . nil)))
                    (B . ((F . nil) (G . nil))))))
=>
(((A C D) (A C E)) ((A B F) (A B G)))

我一定是在递归中遗漏了某种附加/合并,但我没有看到它。

【问题讨论】:

    标签: algorithm data-structures tree common-lisp


    【解决方案1】:

    在这里,我尝试重写它以使其能够线性工作(因为您的原始函数会耗尽堆栈空间)。然而,在这样做的同时,我发现了一些东西,你可能会认为它是你最初的想法:

    (defun tree-to-paths (tree)
      (loop with node = tree
           with trackback = nil
           with result = nil
           with head = nil
           with head-trackback = nil
           while (or node trackback) do
           (cond
             ((null node)
              (setf node (car trackback)
                    trackback (cdr trackback)
                    result (cons head result)
                    head (car head-trackback)
                    head-trackback (cdr head-trackback)))
             ((consp (car node))
              (setf trackback (cons (cdr node) trackback)
                    head-trackback (cons head head-trackback)
                    head (copy-list head)
                    node (car node)))
             (t (setf head (cons (car node) head)
                      node (cdr node))))
           finally (return (nreverse (mapcar #'nreverse result)))))
    

    在您的示例数据中,您想要接收的结果在直觉上似乎是正确的,但您也可以将其视为有更多路径,例如:

    A -> C -> NIL - 从您的数据来看,这个结果似乎是多余的,但一般来说,您可能也希望获得这些结果/通常很难将它们全部过滤掉。

    【讨论】:

      【解决方案2】:

      您必须删除(append (list (tree->paths 中的list

      tree->paths 返回路径列表; recurse 也是如此。因此,它们可能会被附加而不包含在 list 调用中。

      【讨论】:

        【解决方案3】:

        我重新开始并选择了相反的方法,如我在问题中尝试的那样,从叶到根而不是从根到叶:

        (defun tree->paths2 (tree)
          (labels ((recurse (follow-ups)
                 (if follow-ups
                 (append (tree->paths2 (car follow-ups))
                     (recurse (cdr follow-ups)))
                 nil)))
            (rstyu:aif (cdr tree)
                   (mapcar #'(lambda(arg)
                       (cons (car tree) arg))
                       (recurse it))
                   (list tree))))
        
        (tree->paths2 '(A . ((C . ((D . nil) (E . nil)))
                             (B . ((F . nil) (G . nil))))))
        =>
        ((A C D) (A C E) (A B F) (A B G))
        

        但如果有办法修复我的第一种方法,我更愿意接受这样的修复作为答案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-26
          • 2021-02-13
          • 1970-01-01
          • 2013-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-07
          相关资源
          最近更新 更多