我试图编写代码来查找树中的最小级别(最小嵌套子列表数量) 树是这样给出的:
(A (B (E (I))(F))(C (G))(D))
看起来像:
A
/ | \
B C D
/\ |
E F G
|
I
这将导致......等级1.最高等级为等级3,但我只需要最低等级。
我尝试使用min函数,但无论我做什么,它将返回1或0,如果列表为null,我返回0和min(0或任何)总是0.任何想法如何解决这个没有映射/ lambda funct?
我尝试过这样的事情:
(defun nrlevels (tail)
(cond
((null tail) 0)
((listp (car tail))
(min (+ 1 (nrlevels (car tail)))
(nrlevels (cdr tail))))
(t (nrlevels (cdr tail)))))
但正如我所说,min将会比较(最终)0和0最小的东西,最终结果将是0.我不知道如何逃避这个循环。
答案 0 :(得分:2)
您将表示迭代的级别递归和递归都放在一个节点的子节点上。问题是要区分没有孩子的访问节点和到达子列表末尾的访问节点。
你需要分开这些东西。我发现最简单的方法是将迭代放在子列表上loop
:
(defun minimum-child-level (tree)
(if (atom tree)
0
(1+ (loop :for child :in tree
:when (listp child)
:minimize (minimum-child-level child)))))
或reduce
:
(defun minimum-child-level (tree)
(if (atom tree)
0
(1+ (reduce #'min
(mapcar #'minimum-child-level
(remove-if-not #'listp tree))))))
编辑:您可以通过解释 min 累加器并以一种或另一种方式递归来实现,但我不建议将其用于生产代码:
(defun minimum-child-level (tree &optional min-so-far)
(cond ((endp tree) ; end of child list
(if min-so-far
(1+ min-so-far) ; there were children
0)) ; no children
((atom (first tree)) ; ignore symbols, go to next child
(minimum-child-level (rest tree) min-so-far))
(t ; sublist
;; recurse into child
(let ((child-minlevel (minimum-child-level (first tree))))
;; go to next child
(minimum-child-level (rest tree)
(if min-so-far
(min min-so-far child-minlevel)
child-minlevel))))))