【问题标题】:How to get the path to a node in n-ary tree?如何获取n叉树中节点的路径?
【发布时间】:2014-06-16 08:40:00
【问题描述】:

我正在使用 gnu lisp 并希望获取到某个节点的路径。 我已经设法解决了二叉树的问题,但如果二叉树是 n 元,则找不到正确的递归规则。表示树(根 (subtree1) (subtree2) ...)。 那么,如何使用 GNU Lisp 获取 n 叉树中节点的路径?

二进制代码:

;checks if element e is in l
(defun partof(l e)
    (cond
        ((null l) nil)
        ((equal l e) T)
        ((atom l) nil)
        (T (find T (mapcar (lambda (l) (partof l e)) l)))))

;get the path   
(defun path(l e)
    (cond
        ((null l) nil)
        ((equal (car l) e) (list (car l))) ;if the element is the root of subtree return it
        ((partof (cadr l) e) (cons (car l) (path (cadr l) e))) ;if it is in the first subtree, get the root and check in first subtree until you get to it
        ((partof (caddr l) e) (cons (car l) (path(caddr l) e))) ; get the root and parse the second subtree
        (T nil))) ;here i can't find the rule to check in the rest of the subtrees

我也对一种全新的方式感兴趣,而不仅仅是完成这个。 一棵n叉树是这样的: (root (subtree1) (subtree2) (subtree3) ...),例如 (A (B (C) (D)) (E (F) (G)) (H ( I) (J))) 是一棵完整的树。

                   A
               /   |   \
              B    E    H
             /\    /\   /\
            C D   F G  I J

【问题讨论】:

  • "表示树(根 (subtree1) (subtree2) ...)。你能澄清一下树的结构吗?你想返回什么作为路径?
  • 我举了一个树的例子。从根到节点的路径(传递给请求节点的所有节点)。通往 D 的路径:A、B、D。
  • 您也可能对this post感兴趣。
  • @Mark,这篇文章是针对二叉树的。我为此编写了解决方案,我对 n-ary 树感兴趣。谢谢。
  • @CristiDeac Stack Overflow 是一个面向专业和狂热程序员的网站。大多数专业和狂热的程序员都会欣赏类似问题的解决方案的参考,因为专业和狂热的程序员愿意考虑类似情况的解决方案,如何修改它们以适应新的问题情况。 Mark 并没有声称该帖子会解决您的问题,只是说它相似并且可能有用或有趣。 Stack Overflow 不是代码工厂。解决某些特定问题的高要求代码并不是获得有用结果的最佳方式

标签: tree lisp


【解决方案1】:

从根到节点的路径(递归方法)

(defun find-path (tree node &optional path)
  (if (eq (car tree) node)
      (reverse (cons node path))
      (reduce (lambda (p x)
                (or p (find-path x
                                 node
                                 (cons (car tree) path))))
              (cdr tree)
              :initial-value nil)))

适用于 GNU CLISP 2.49:

CL-USER> (defparameter *tree* '(a (b (c) (d)) (e (f) (g)) (h (i) (j))))
*TREE*
CL-USER> (find-path *tree* 'd)
(A B D)

从一个任意节点到另一个节点的路径

OP 没有说他/她想要获得什么样的路径:从根到节点,或两个任意节点之间。所以这个函数解决了在树的两个任意节点之间寻找路径的更一般的任务。

(defun find-path* (tree x y)
  (labels ((till-d (a b i)
             (if (and (eq (car a) (car b))
                      a
                      b)
                 (till-d (cdr a) (cdr b) (1+ i))
                 i)))
    (let* ((x-path (find-path tree x))
           (y-path (find-path tree y))
           (pos (till-d x-path y-path 0)))
      (append (reverse (nthcdr (1- pos) x-path))
              (nthcdr pos y-path)))))

像这样工作:

CL-USER> (find-path* *tree* 'd 'c)
(D B C)
CL-USER> (find-path* *tree* 'd 'g)
(D B A E G)
CL-USER> (find-path* *tree* 'b 'h)
(B A H)
CL-USER> (find-path* *tree* 'd 'd)
(D)

现在许多任务也可以很容易地解决(节点之间的距离等)。

【讨论】:

  • 很好的解决方案!谢谢!
【解决方案2】:

记住我学到的关于食谱和“相信递归”的知识,我可以提供以下内容:

CL-USER> (defun path (tree elt)
           (labels ((find-path (tree elt path)
                      (cond ((null tree) nil)
                            ((equal (car tree) elt) (cons elt path))
                            (t (some #'(lambda (sub)
                                         (find-path sub elt (cons (car tree) path)))
                                     (cdr tree))))))
             (reverse (find-path tree elt '()))))
STYLE-WARNING: redefining COMMON-LISP-USER::PATH in DEFUN(A (B (C) (D)) (E (F) (G)) (H (I) (J)))
PATH
CL-USER> (path '(A (B (C) (D)) (E (F) (G)) (H (I) (J))) 'D)
(A B D)

请注意,我在这里一直在使用 SBCL,但它至少应该给你一个想法......

【讨论】:

    【解决方案3】:

    这与查找二叉树节点的路径没有什么不同。 .有我发布的二叉树的解决方案..您可以为 N 路树实现相同的解决方案。

    //不是为左右孩子调用递归函数,你必须编写一个循环来调用所有孩子,你会得到它。

    package binary_tree_path;

    导入 java.util.ArrayList;

    /* * 给你一棵二叉树(根节点).. 并且给定一个可能/可能不在树中的键。 您必须找到从根到节点的完整路径。

    例子

                    A
               /           \
           B                C
             \               /
              D           E
            /    \           \
          K      L        M
        /
    Z
    

    您已经给定节点 Z(或节点的键)并给定节点 A(root) 所以你的输出应该是

    A B D K Z

    如果给定 M 输出应该是 A C E M

    */

    公共类 main_class { 公共静态 void main(String args[] ) {

        //first create tree
        Node rootNode = new Node ('A' , new Node('B',null,
                                                 new Node('D',
                                                          new Node('K',
                                                                   new Node('Z',null,
                                                                   null),null),
                                                          new Node('L',null,null))),
                                        new Node('C',
                                                 new Node('E',
                                                          null,
                                                          new Node('M',null,null)),null) );
    
        ArrayList <Node> path = new ArrayList<Node>();
        System.out.println(getPath(rootNode,'Z',path));
        System.out.println(path);
        path = new ArrayList<Node>();
        System.out.println(getPath(rootNode,'M',path));
        System.out.println(path);
    
    }
    static boolean getPath(Node rootNode, char key, ArrayList<Node> path ){
        //return true if the node is found
        if( rootNode==null)
            return false;
        if (rootNode.getVal()==key){
            path.add(rootNode);
            return true;
        }
        boolean left_check = getPath( rootNode.left,key,path);
        boolean right_check = getPath( rootNode.right,key,path);
        if ( left_check || right_check){
            path.add(rootNode);
            return true;
        }
        return false;
    
    }
    static class Node {
        char val;
        Node left;
        Node right;
        public Node( char val, Node left, Node right){
            this.left=left;
            this.right=right;
            this.val=val;
        }
        public char getVal(){
            return val;
        }
       public String toString(){
            return " " + val + " ";
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2019-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-27
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多