我有一个看起来像(A(B(C D))(E(F)))的列表代表这棵树:
A
/ \
B E
/ \ /
C D F
如何将其打印为(A B E C D F)?
这是我管理的:
((lambda(tree) (loop for ele in tree do (print ele))) my-list)
但它打印出来:
A
(B (C D))
(E (F))
NIL
我对Common LISP很新,所以可能会有我应该使用的功能。如果是这样的话,那就让我开心吧。
感谢。
答案 0 :(得分:5)
以面值来表达您的问题,您希望以“广度优先”顺序打印出节点,而不是使用标准的深度优先排序之一:“按顺序”或“预订”或'后序'。
订购后:C D B F E A
请求订单:A B E C D F
在树结构中,每个元素可以是原子,也可以是包含一个元素的列表,也可以是包含两个元素的列表。列表的第一个元素始终是原子。
我认为伪代码看起来像是近似的:
Given a list 'remains-of-tree':
Create empty 'next-level' list
Foreach item in `remains-of-tree`
Print the CAR of `remains-of-tree`
If the CDR of `remains-of-tree` is not empty
CONS the first item onto 'next-level'
If there is a second item, CONS that onto `next-level`
Recurse, passing `next-level` as argument.
我100%肯定可以清理(看起来像琐碎的尾递归,除此之外的所有其他)。但是,我认为它有效。
Start: (A (B (C D)) (E (F)))
Level 1:
Print CAR: A
Add (B (C D)) to next-level: ((B (C D)))
Add (E (F)) to next-level: ((B (C D)) (E (F)))
Pass ((B (C D) (E (F))) to level 2:
Level 2:
Item 1 is (B (C D))
Print CAR: B
Push C to next-level: (C)
Push D to next-level: (C D)
Item 2 is (E (F))
Print CAR: E
Push F to next-level: (C D F)
Pass (C D F) to level 3:
Level 3:
Item 1 is C
Print CAR: C
Item 2 is D
Print CAR: D
Item 3 is F
Print CAR: F
答案 1 :(得分:2)
您表示列表的方式似乎不一致。对于你的例子,我想它应该是:(A ((B (C D)) (E (F))))
。这样,节点始终是叶子或列表,其中汽车是叶子,而cadr是子节点。
由于这个错误,我假设这不是一个功课。这是一个递归解决方案。
(defun by-levels (ts)
(if (null ts)
'()
(append
(mapcar #'(lambda (x) (if (listp x) (car x) x)) ts)
(by-levels (mapcan #'(lambda (x) (if (listp x) (cadr x) '())) ts)))))
by-levels
获取节点列表并收集顶级节点的值,并递归地查找下一个要用作下一个节点的子节点。
现在,
(defun leafs-of-tree-by-levels (tree)
(by-levels (list tree)))
(leafs-of-tree-by-levels '(a ((b (c d)) (e (f)))))
; (A B E C D F)
我希望这是有道理的。
答案 2 :(得分:1)
我的Lisp有点生疏,但正如Jonathan建议的那样,广度优先的树木行走应该这样做 - 沿着这些方向行事
编辑:我想我以前读过这个问题的时间太快了。你所拥有的基本上是函数应用程序的语法树,所以这里是修改后的代码。我从你对问题的描述中假设,如果C和D是B的孩子,那么你打算写(B(C)(D))
; q is a queue of function calls to print
(setq q (list the-original-expression))
; for each function call
(while q
; dequeue the first one
(setq a (car q) q (cdr q))
; print the name of the function
(print (car a))
; append its arguments to the queue to be printed
(setq q (append q)(cdr a))
)
这是历史:
q: ( (A (B (C)(D))(E (F))) )
print: A
q: ( (B (C)(D))(E (F)) )
print: B
q: ( (E (F))(C)(D) )
print: E
q: ( (C)(D)(F) )
print: C
q: ( (D)(F) )
print: D
q: ( (F) )
print: F
q: nil