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

时间:2009-11-12 12:00:05

标签: recursion lisp binary-tree

我有以下二叉树

  A
 / \
 B  C
   / \
  D   E

表示为Lisp中的列表(A 2 B 0 C 2 D 0 E 0),其中字母是节点名称,数字是子节点的数量(0表示无,1表示1个节点,2表示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))))) 

但它无法正常工作。我也浏览了类似的帖子,但我找不到任何有用的东西可以帮助我。有人可以给我一个建议来帮助解决这个问题吗?谢谢!

P.S。这是我将在大学展示的一个小项目的一部分,也是我自己在Lisp中变得更好的方式(我看到很多类似的帖子都有问题询问帖子是否与家庭作业有关)。 :)

4 个答案:

答案 0 :(得分:3)

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

(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)

答案 1 :(得分:2)

我首先将列表转换为树:

(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)))

我想知道你是否不能从这个树表示开始。

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

答案 2 :(得分:1)

这是延续传递方式中的一个:

(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)))))

答案 3 :(得分:0)

使用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))))

感谢Artelius和Svante的帮助!