Recursion 在LISP中递归计算二叉树的深度

Recursion 在LISP中递归计算二叉树的深度,recursion,lisp,binary-tree,Recursion,Lisp,Binary Tree,我有下面的二叉树 A / \ B C / \ D E A. / \ B C / \ D E 在Lisp中表示为一个列表(a 2 B 0 C 2 D 0 E 0),其中字母是节点名称,数字是子节点数(0表示无,1表示一个节点,2表示两个节点)。我需要递归地找到树从根节点到叶的最大深度(即二叉树的深度)。我是Lisp的新手,不知道如何实现它。到目前为止,我一直在想: (defun depth (tree) "Returns the depth of the argument

我有下面的二叉树

A / \ B C / \ D E A. / \ B C / \ D E 在Lisp中表示为一个列表(a 2 B 0 C 2 D 0 E 0),其中字母是节点名称,数字是子节点数(0表示无,1表示一个节点,2表示两个节点)。我需要递归地找到树从根节点到叶的最大深度(即二叉树的深度)。我是Lisp的新手,不知道如何实现它。到目前为止,我一直在想:

(defun depth (tree) "Returns the depth of the argument tree." (check-type tree list) (if (= (second tree) 0) 0 (1+ (get-btree-max-depth (cddr tree))))) (defun get-btree-max-depth (btree) "Returns the maximum depth of the argument tree." (check-type btree list) (if (= (second btree) 0) 0 (max (depth (cddr btree)) (get-btree-max-depth (cddr btree))))) (defun深度(树) “返回参数树的深度。” (检查类型树列表) (如果(=(第二棵树)0) 0 (1+(获取btree最大深度(cddr树(()()))) (取消获取btree最大深度(btree) “返回最大深度 参数树的一部分。” (检查类型B树列表) (如果(=(第二个btree)0) 0 (最大深度(cddr btree)) (获取btree最大深度(cddr btree(()()))) 但它不能正常工作。我也浏览了类似的帖子,但没有发现任何有用的东西可以帮助我。有人能给我一个建议帮我解决这个问题吗?谢谢大家!


另外,这是我将在大学里展示的一个小项目的一部分,也是我自己提高Lisp水平的方法(我看到许多类似的帖子都有问题,问这个帖子是否与家庭作业有关):)

我首先将列表转换为一棵树:

(defun tlist->tree (tlist)
  "Transforms a tree represented as a kind of plist into a tree.
   A tree like:
               A
              / \
             B   C
            /   / \
           F   D   E
   would have a tlist representation of (A 2 B 1 F 0 C 2 D 0 E 0).
   The tree representation would be (A (B (F)) (C (D) (E)))"
  (let (tree)
    (push (pop tlist) tree)
    (dotimes (i (pop tlist))
      (multiple-value-bind (subnode rest-tlist) (tlist->tree tlist)
        (push subnode tree)
        (setf tlist rest-tlist)))
    (values (nreverse tree) tlist)))
我想知道您能否从这个树表示开始


然后,在树表示法中查找树的深度是一个简单的递归一行。

使用Artelius和Svante的答案,我设法解决了这个问题。这是代码,也许它会对其他需要帮助的人有所帮助

(defun btree-max-depth (btree) "Returns the maximum depth of the binary tree." (check-type btree list) (if (null btree) 0 ; the max depth of the members of () (max (depth (first btree)) (btree-max-depth (rest btree))))) (defun depth (tree) "Returns the depth of the argument TREE." (if (atom tree) 0 ; an atomic tree has a depth of 0 (1+ (btree-max-depth tree)))) (卸载btree最大深度(btree) “返回最大深度 二叉树的一部分。” (检查类型B树列表) (如果(空b树) 0;的成员的最大深度() (最大深度(第一棵树)) (B树最大深度(剩余B树(()()))) (defun深度(树) “返回参数树的深度。” (如果(原子树) 0;原子树的深度为0 (1+(b树最大深度树)))
感谢阿泰利乌斯和斯万特的帮助

这个怎么样?不需要对树进行转换

(defun depth-rec (tree)
  (labels ((depth-rec-aux (depth)             ; self-recursive function
             (if (null tree)                  ; no more nodes
                 depth                        ;   -> return the current depth
               (let ((n (second tree)))       ; number of subnodes
                 (pop tree) (pop tree)        ; remove the current node
                 (case n
                   (0 (1+ depth))                     ; no subnode,  1+depth
                   (1 (depth-rec-aux (1+ depth)))     ; one subnode, its depth+1
                   (2 (max (depth-rec-aux (1+ depth)) ; two subnodes, their max
                           (depth-rec-aux (1+ depth)))))))))
    (depth-rec-aux 0)))                       ; start depth is 0
另一个版本:

(defun depth-rec (tree &aux (max 0))
  (labels ((depth-rec-aux (depth)
             (when tree
               (pop tree)
               (let ((n (pop tree)))
                 (if (zerop n)
                     (setf max (max max (1+ depth)))
                   (loop repeat n do (depth-rec-aux (1+ depth))))))))
    (depth-rec-aux 0))
  max)

下面是一个延续传球方式:

(defun oddtree-height (oddtree)
  (suboddtree-height oddtree
                     #'(lambda (h remainder)
                         (if (null remainder) h nil))))

(defun suboddtree-height (oddtree c)
  (max-height-of-suboddtrees (cadr oddtree)
                             0
                             (cddr oddtree)
                             #'(lambda (h remainder)
                                 (funcall c (+ h 1) remainder))))

(defun max-height-of-suboddtrees (n best oddtree c)
  (if (= n 0)
      (funcall c best oddtree)
    (suboddtree-height oddtree
                       #'(lambda (h remainder)
                           (max-height-of-suboddtrees (- n 1) (max best h) remainder c)))))

首先将树转换为更好的格式!也就是说,树应该是树的列表。(二叉树应该是不超过2个二叉树的列表)。记住,列表可以包含列表!当你想写递归函数时,使用递归数据结构是有意义的。如果在B下面有另一个节点F,那么树会被表示为
(a2b1f0c2d0e0)
还是
(a2b1c2f0d0e0)
?它会被表示为(node list-of-child-nodes1-list-of-child-nodes2…)因此,在B下面有一个F节点的树将是(a2b1f0c2d0e0),简单的一行是:
(defun depth(tree)(1+)(apply#'max-1(mapcar#'depth(rest tree###'depth(rest tree!#))));
,假设深度被定义为向下的最大边数。我恐怕不得不重新考虑我昨天给出的答案。似乎其中一个条件是不将描述树的列表从一种格式转换为另一种格式,因此我回到了一个起点,即不知道如何解析列表和计算二叉树的深度。我们欢迎并非常感谢任何关于如何做到这一点的建议。谢谢