LISP二叉树 - 最大深度

时间:2014-12-14 10:48:11

标签: tree lisp common-lisp

使用这种表示树的方式:( A(B)(C(D)(E)))(从我所看到的,我认为这是标准方式,但我可能错了)。

  A
 / \
 B  C
   / \
   D  E 

我想找到最大深度,并构建一个包含从根到该级别的节点的列表。 对于上面的示例,答案为2(根位于0级),其中包含以下两个列表之一:(A C D)或(A C E)。

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

CAR树应该给我左侧子树,CDR树应该给我正确的树。如果我到达终点或原子(这感觉不对)我停下来。我检查maxdepth(car l)是否大于maxdepth(cdr l)并且更大一些。 但这给了我8以上的树。我还没有开始构建列表。

我是一个好主意和一个好的实施有多远?

2 个答案:

答案 0 :(得分:3)

在您正在使用的表示中,(car l)是当前节点,(cadr l)是左子树,(caddr l)是正确的子树。所以你的递归步骤应该是:

(+ 1 (max (maxdepth (cadr l)) (maxdepth (caddr l)))

您还错过了t默认条款中的cond条件。所以完整版应该是:

(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

答案 1 :(得分:2)

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

在根部,骨架看起来像这样(假设是二叉树):

(defun max-depth (tree)
  (if (null (rest tree))
      (values 0 tree)
      (with-sub-depths (left-depth left-path right-depth right-path tree)
        (if (> right-depth left-depth)
            (values (1+ right-depth) (cons (car tree) right-path))
            (values (1+ left-depth) (cons (car tree) left-path))))))

With-sub-depths现在是实际递归的占位符。

假设我们让这个工作,max-depth将返回所需的两个值。如果我们只是调用它并使用它的返回值,我们得到第一个(主要)值:

(let ((d (max-depth tree)))
  (format t "Depth is ~a." d))

如果我们需要其他值,我们可以使用multiple-value-bind

(multiple-value-bind (depth path) (max-depth tree)
  (format t "Depth is ~a.  Example path: ~s." depth path))

我们现在也需要在递归中使用multiple-value-bind

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