查找树中最深的节点(Lisp)

时间:2015-03-03 22:40:33

标签: tree lisp common-lisp tree-traversal postorder

我希望通过使用列表形式的树来查看lisp中的树并找到最深的(或距离根节点最远)。到目前为止,我的想法是继续将树切割成左右子树(假设父节点将只有两个儿子,如二进制树)我将在下面发布我的代码,因为虽然它编译它给了我nil的错误不是真正的类型。任何建议都会很好甚至改进代码!

我已经看到类似的问题,找到节点之间的路径,但我们真的看不到有关如何将最深的节点实际打印到屏幕上的任何有用的信息。

谢谢你的期待。

(defun postorder(tree)
 (cond ((null tree) 0)
    ((< (list-length tree) 3) 0)
    (t 
     (append (postorder (left-subtree tree))
        (postorder (right-subtree tree))
        (list (car tree))))))

(defun tree-depth (sub-tree)
 (cond ((null sub-tree) nil)
    ((atom sub-tree) nil)
    (t (+ 1 (max (tree-depth (cadr sub-tree)) (tree-depth (caddr sub-tree)))))))

(defun left-subtree(tree)
 (cond ((null tree) nil)
    ((not (listp tree)) nil)
 (t (car (cdr tree)))))

(defun right-subtree(tree)
 (cond ((null tree) nil)
    ((not (listp tree)) nil)
    (t (car (cdr (cdr tree))))))

(defun split-tree (tree)
 (cond ((null tree) 
    tree)
    ((> (tree-depth (left-subtree tree)) (tree-depth (right-subtree tree)))
       (split-tree (left-subtree tree)))
    ((< (tree-depth (left-subtree tree)) (tree-depth (right-subtree tree)))
       (split-tree (right-subtree tree)))
    ((= (tree-depth (left-subtree tree)) (tree-depth (right-subtree tree)))
       (first (postorder tree)))))

输入将是&#39;(1(2(4)(6))(5(7)(8))))

2 个答案:

答案 0 :(得分:0)

我只是想你必须致电tree-depth而不是postorder。虽然答案基本保持不变: 只要您使用trace获取调用树:

(trace tree-depth)

(tree-depth '(1 (2 (4) (6)) (5 (7) (8))))

0: (TREE-DEPTH (1 (2 (4) (6)) (5 (7) (8))))
1: (TREE-DEPTH (2 (4) (6)))
  2: (TREE-DEPTH (4))
    3: (TREE-DEPTH NIL)
    3: TREE-DEPTH returned NIL
    3: (TREE-DEPTH NIL)
    3: TREE-DEPTH returned NIL

因此,您现在获得了两个tree-depth递归调用的返回值,两者都是nil。但是现在你的代码想要对它们进行+,因为nilnil都不属于类型REAL(因为你的翻译已经告诉过你),这会导致失败。因此,如果您想继续使用当前的解决方案,则需要修复递归逻辑以确保此案例得到满足。

如果您查看树的图纸

,修复实际上看起来非常直观
lvl             tree
3                1
2       2               5
1    4     6        7       8
0

因此(null subtree)应返回值0。只要您坚持使用所选择的树表示,就不会出现(atom subtree)个案例。

(defun tree-depth (sub-tree)
 (cond ((null sub-tree) 0)
    (t (+ 1 (max (tree-depth (cadr sub-tree)) (tree-depth (caddr sub-tree)))))))

我认为另一种解决方案可能看起来像这样(稍微短一些):

(defun find-deepest (tree)
  (reduce #'(lambda(l c)
          (if (> (car c)
                 (car l))
          c
          l))
      (mapcar #'(lambda (node)
              (if (listp node)
              (let ((found (find-deepest node)))
                (cons (+ (car found) 1) (cdr found)))
              (cons 1 node)))
          tree)))

  > (find-deepest '(1 (2 (4) (6)) (5 (7) (8))))
  (3 . 4)

或者,如果您只关心价值

  > (cdr (find-deepest '(1 (2 (4) (6)) (5 (7) (8)))))
  4

或者如果您只关心深度

  > (car (find-deepest '(1 (2 (4) (6)) (5 (7) (8)))))
  3

答案 1 :(得分:0)

这个怎么样?编辑:对不起,没有看到上面的简短回答。 “无论如何,我会留在这里

。”
(defun tag-and-flatten (tree &optional (depth 0))
  (cond ((null tree) nil)
        ((atom tree) (list (list tree depth)))
        (t (apply #'append (mapcar (lambda (x) (tag-and-flatten x (1+ depth))) tree)))))

(defun find-deepest (tree)
  (caar (sort (tag-and-flatten tree) #'> :key #'second)))

测试

> (find-deepest '(1 (2 (4) (6)) (5 (7) (8))))
4

> (find-deepest '(:a :b ((((:c))) :d)))
:c