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