Tree LISP二叉树-最大深度

Tree LISP二叉树-最大深度,tree,lisp,common-lisp,Tree,Lisp,Common Lisp,使用这种表示树的方法:(A(B)(C(D)(E))(据我所见,我认为这是标准的方法,但我可能错了) 我想找到最大深度,并构建一个从根节点到该级别节点的列表。 对于上面的例子,答案是2(根在0级),有以下两个列表之一:(acd)或(ace) maxdepth算法应该很简单: maxdepth( tree ): if ( !tree ) return 0 leftdepth = maxdepth( left sub-tree ) rightdepth = maxd

使用这种表示树的方法:(A(B)(C(D)(E))(据我所见,我认为这是标准的方法,但我可能错了)

我想找到最大深度,并构建一个从根节点到该级别节点的列表。 对于上面的例子,答案是2(根在0级),有以下两个列表之一:(acd)或(ace)

maxdepth算法应该很简单:

maxdepth( tree ):
    if ( !tree )    return 0
    leftdepth   = maxdepth( left sub-tree )
    rightdepth  = maxdepth( right sub-tree )
    return max ( leftdepth + 1, rightdepth + 1 ) 
所以我尝试了类似的方法:

(defun maxdepth(l)
    (cond
        ((null l) 0)
        ((atom l) 0)
        ((+ 1 (max (maxdepth(car l)) (maxdepth(cdr l)))))
    )
)
汽车树应该给我左边的子树,CDR树应该给我右边的子树。如果我到达终点或一个原子(感觉不对),我就会停下来。我检查maxdepth(car l)是否大于maxdepth(cdr l),并进一步使用更大的。 但是上面这棵树给了我8分。我还没有开始构建这个列表


我离一个好主意和一个好的实现还有多远

在您使用的表示中,
(car l)
是当前节点,
(cadr l)
是左子树,
(caddr l)
是右子树。因此,递归步骤应该是:

(+ 1 (max (maxdepth (cadr l)) (maxdepth (caddr l)))
(defun maxdepth (l)
  (cond ((null l) 0)
        ((atom l) 0)
        (t (+ 1 (max (maxdepth (cadr l)) (maxdepth (caddr l)))))))

(maxdepth '(A (B) (C (D) (E))))
您的
cond
的default子句中也缺少
t
条件。因此,完整版本应为:

(+ 1 (max (maxdepth (cadr l)) (maxdepth (caddr l)))
(defun maxdepth (l)
  (cond ((null l) 0)
        ((atom l) 0)
        (t (+ 1 (max (maxdepth (cadr l)) (maxdepth (caddr l)))))))

(maxdepth '(A (B) (C (D) (E))))

返回
3

我理解您的要求是希望返回两个值:深度和从根到全深度的一个(任意)路径。这是一个展示如何使用多值语义的好机会

在根目录处,骨架如下所示(假设为二叉树):

带有子深度的
是目前实际递归的占位符

假设我们能够实现这一点,
max depth
将返回所需的两个值。如果我们只调用它并使用其返回值,我们将得到第一个(主)值:

如果我们需要额外的值,我们可以使用
多值绑定

(multiple-value-bind (depth path) (max-depth tree)
  (format t "Depth is ~a.  Example path: ~s." depth path))
我们现在也需要在递归中使用
多值绑定

(defun max-depth (tree)
  (if (null (rest tree))
      (values 0 tree)
      (multiple-value-bind (left-depth left-path) (max-depth (second tree))
        (multiple-value-bind (right-depth right-path) (max-depth (third tree))
          (if (> right-depth left-depth)
              (values (1+ right-depth) (cons (first tree) right-path))
              (values (1+ left-depth) (cons (first tree) left-path)))))))
在REPL处尝试此操作将显示返回的所有值:

CL-USER> (max-depth '(A (B) (C (D) (E))))
2
(A C D)

这实际上是我犯的一个明显的错误。我想我会浪费很多时间去弄清楚。现在,当涉及到构建列表时:每次选择子树时都附加当前节点是一个好主意吗?如果要进入子树,则不再需要父节点。在这里,我构建了列表,然后将其传递到length,认为我不能同时做这两件事。这很好:)
CL-USER> (max-depth '(A (B) (C (D) (E))))
2
(A C D)