如何获取n-ary树中节点的路径?

时间:2014-06-16 08:40:00

标签: tree lisp

我在gnu lisp工作,想要获取某个节点的路径。 我设法解决了二叉树的问题,但如果树是n-ary,则无法找到正确的递归规则。表示树(root(subtree1)(subtree2)...)。 那么,如何使用GNU Lisp获取n-ary树中节点的路径?

二进制代码:

;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-ary树是这样的:(root(subtree1)(subtree2)(subtree3)...),例如(A(B(C)(D))(E(F)(G))(H( I)(J)))是一棵完整的树。

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

3 个答案:

答案 0 :(得分:1)

记住我对食谱的了解和信任递归",我可以提供以下内容:

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,但至少应该给你一个想法......

答案 1 :(得分: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 :(得分:-2)

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

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

package binary_tree_path;

import java.util.ArrayList;

/ *  *您将获得一个二叉树(根节点)..并且给出了一个可能/可能不在树中的密钥。 您必须找到从根到节点的完整路径。

示例

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

您已经给出了节点Z(或节点的密钥)和给定的节点A(根) 所以你的输出应该是

A B D K Z

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

* /

public class main_class {     public static 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 + " ";
    }
}

}