在lisp中的树遍历

时间:2016-05-04 04:15:40

标签: recursion lisp

我试图在lisp中遍历一棵树并打印出所有父子关系。 这是我的输入:(5(3(4(1))(g)(9(6)))(n(8(0))(q)(7)(b(f(c(a))) ))) 我试图让它打印出以下内容:

5>3

5>n

3>4

3>g

3>9

4>1

9>6

n>8

n>q

n>7

n>b

8>0

b>f

f>c

c>a

我目前的代码如下:

(defun par-child-print (l)
    (print l)
    (cond ((not (null (caadr l))) 
    (print "start")
    (print (car l)) 
    (print ">") 
    (print (caadr l)) 
    (print "end")
    (cond ((not (atom (car l))) (when (not (eq (car l) NIL)) (par-child-print (car l)))));

    (when (not (eq (cdr l) NIL)) (par-child-print (cdr l)))

    )
(t 
)));

问题是我的输出有时只打印父级(并且它也不会通过整个树)。有什么想法吗?

我也有这个通过整个树,但是甚至没有试图跟踪父母:

(defun atom-print (l)
(print l)
(cond ((atom l) (print l));
(t 
(when (not (eq (car l) NIL)) (atom-print (car l)))
(when (not (eq (cdr l) NIL)) (atom-print (cdr l)))


)));

2 个答案:

答案 0 :(得分:6)

树中的每个列表由两部分组成,一个名称和一个子列表。这些与列表的CARCDR相同,但出于语义原因,您可以从为它们定义别名开始:

(defun name (tree) (car tree))
(defun children (tree) (cdr tree))

这些摘要了解树的实现细节。然后,给定一棵树,你想做两件事:

  1. 使用父母姓名和孩子名称为每个孩子打印一行。这可以这样做:

    (dolist (child (children tree))
      (format t "~&~a > ~a" (name tree) (name child)))
    
  2. 以相同方式打印每个孩子。这是通过递归调用函数来完成的:

    (dolist (child (children tree))
      (print-tree child))
    
  3. 所以整个函数看起来像这样:

    (defun print-tree (tree)
      (dolist (child (children tree))
        (format t "~&~a > ~a" (name tree) (name child)))
      (dolist (child (children tree))
        (print-tree child)))
    
    (print-tree '(5 (3 (4 (1)) (g) (9 (6))) (n (8 (0)) (q) (7) (b (f (c (a)))))))
    ; 5 > 3
    ; 5 > N
    ; 3 > 4
    ; 3 > G
    ; 3 > 9
    ; 4 > 1
    ; 9 > 6
    ; N > 8
    ; N > Q
    ; N > 7
    ; N > B
    ; 8 > 0
    ; B > F
    ; F > C
    ; C > A
    

答案 1 :(得分:0)

jkiiski's answer存在问题:它适用于给定的输入,但仅限于每个child都有自己的children。这个答案的变体在样本输入上具有相同的行为,但这也适用于其他树。

(defun print-tree (tree)
  (dolist (child (cdr tree))
    (format t "~&~a > ~a" (car tree) (if (consp child)
                                         (car child)
                                       child)))
  (dolist (child (cdr tree))
    (if (consp child)
        (print-tree child))))


(print-tree '(A (B (C 1 2 3) 4)))
A > B
B > C
B > 4
C > 1
C > 2
C > 3