【问题标题】:tree traversal inorder LISP树遍历中序 LISP
【发布时间】:2016-03-14 00:49:37
【问题描述】:

我正在尝试返回按顺序访问的树(不一定是二叉树)的节点列表。

树表示为带有子列表的列表,例如:(a (b) (c (d) (e))), b - left-subtree, (c (d) (e)) - right-子树,一个-root。 结果应该是:b,a,d,c,e

这是我的代码,但我似乎总是收到“堆栈溢出”错误。有人可以帮帮我吗?

;return left-subtree
(defun left-tree(tree)
  (cond
   ((null tree) NIL)
   ((not (listp tree)) NIL)
   (t (car (cdr tree)))
  )
)

;return right-tree
(defun right-tree(tree)
  (cond
   ((null tree) NIL)
   ((not (listp tree)) NIL)
   (t (cdr (cdr tree)))
  )
)

;perform inorder
(defun inorder(tree)
  (if (not (list-length tree)) 0
  (append
   (inorder (left-tree tree))
   (list (car tree))
   (inorder (right-tree tree))
  )
 )
)

【问题讨论】:

  • (not (list-length tree)) 的目的是什么?一个数字的not 总是假的。
  • 树遍历的顺序通常是前序的(根、左、右);后序(左、右、根);并按顺序(左,根,右)。我知道您发布了一个输出示例,但是当您有两个以上的孩子时,“按顺序”应该是什么意思?例如,如果你有树 (a (b) (c) (d)),那么有序遍历应该是什么? a b a c a d?
  • 另一个问题是,您在每次评估 inorder 时都会创建一个新列表,而您希望最终得到一个平面列表。 Common Lisp: A Gentle Introduction to Symbolic Computation 中关于car/cdr recursion 的部分可能会对您有所帮助。
  • 请正确格式化您的代码(缩进和括号放置)。因为它不是,所以很难读。

标签: tree lisp common-lisp inorder


【解决方案1】:

无限递归是由于一个数字永远不会是假的。
(not (list-length tree)) 替换为(null tree)
(也就是说,在结构上递归,而不是在大小上。)

修复此问题后,您将收到类型错误,因为您的基本情况结果为 inorder - 它应该是 nil,而不是 0

一旦你修复了那个,你会发现另一个问题:

CL-USER> (inorder '(a (b) (c (d) (e))))
(B A (C (D) (E)))

这远非正确。

如果您查看right-tree 的结果,实际上并不是您声称的结果:

CL-USER> (right-tree '(a (b) (c (d) (e))))
((C (D) (E)))

如您所见,这是一个单元素列表,其中包含右子树,而不是右子树。
(单独测试每个函数是个好主意,尤其是当您确定它们是正确的时。)

根是第一个列表项(car),左子树是第二个(cdr - cadrcar),右子树是第三个cdrcdrcar - caddr),而不是您写的从第三项开始的列表的其余部分。
您需要提取子树:

(defun right-tree(tree)
  (cond
    ((null tree) NIL)
    ((not (listp tree)) NIL)
    (t (caddr tree))))

CL-USER> (inorder '(a (b) (c (d) (e))))
(B A D C E)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    • 2021-10-30
    相关资源
    最近更新 更多