【问题标题】:Calculating the depth of a binary tree in LISP recursively递归计算LISP中二叉树的深度
【发布时间】:2010-12-15 20:32:39
【问题描述】:

我有以下二叉树

一种 / \ 乙丙 / \ 德

在 Lisp (A 2 B 0 C 2 D 0 E 0) 中表示为一个列表,其中字母是节点名称,数字是子节点的数量(0 表示无,1 表示一个节点,2 表示两个节点)。我需要递归地找到从根节点到树的叶深度(二叉树的深度)的最高值。我对 Lisp 很陌生,我不知道如何实现它。到目前为止,这是我设法提出的:

(定义深度(树) “返回参数树的深度。” (检查类型树列表) (如果(=(第二棵树)0) 0 (1+ (get-btree-max-depth (cddr 树))))) (defun get-btree-max-depth (btree) "返回最大深度 论点树。” (检查类型 btree 列表) (如果 (= (第二个 btree) 0) 0 (最大(深度(cddr btree)) (get-btree-max-depth (cddr btree)))))

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

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

【问题讨论】:

  • 首先将树转换为更好的格式!
  • 即树应该是树的列表。 (二叉树应该是不超过 2 个二叉树的列表)。请记住,列表可以包含列表!当您想编写递归函数时,使用递归数据结构是有意义的。
  • 如果B下面还有一个节点F,那么树会表示为(A 2 B 1 F 0 C 2 D 0 E 0)还是(A 2 B 1 C 2 F 0 D 0 E 0)
  • 它将被表示为 (node list-of-child-nodes1 list-of-child-nodes2 ...) 所以在 B 下面有一个 F 节点的树将是 (A 2 B 1 F 0 C 2 D 0 E 0)

标签: recursion lisp binary-tree


【解决方案1】:

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

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

【讨论】:

    【解决方案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)))
    

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

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

    【讨论】:

      【解决方案3】:

      这是一种延续传递风格:

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

      【讨论】:

        【解决方案4】:

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

        (defun btree-max-depth (btree) "返回最大深度 的二叉树。” (检查类型 btree 列表) (如果(空 btree) 0; () 成员的最大深度 (最大(深度(第一个 btree)) (btree-max-depth (rest btree))))) (定义深度(树) “返回参数树的深度。” (如果(原子树) 0;原子树的深度为 0 (1+ (btree-max-depth 树))))

        感谢 Artelius 和 Svante 的帮助!

        【讨论】:

        • 简单的单行代码应该是:(defun depth (tree) (1+ (apply #'max -1 (mapcar #'depth (rest tree))))),假设深度定义为向下的最大边数。
        • 恐怕我必须重新考虑我昨天给出的答案。似乎其中一个条件不是将描述树的列表从一种格式转换为另一种格式,所以我回到了不知道如何解析列表和计算深度的起点二叉树。欢迎并非常感谢任何建议如何做到这一点。谢谢
        猜你喜欢
        • 2015-02-12
        • 2015-04-08
        • 2022-01-25
        • 2010-12-24
        • 2013-02-19
        • 2020-02-21
        • 2016-01-17
        • 2011-02-15
        • 1970-01-01
        相关资源
        最近更新 更多