在Lisp中搜索二叉树

时间:2014-11-16 12:23:00

标签: tree common-lisp

我被要求创建一个用户指定目标和二叉树的函数,然后该函数将返回到达该节点所需的路径。

即用户将提供此信息(searchtree'b'(((a.b).c)。(d。((e。f)。g))))并且控制台将向左打印。< / p>

我有几个问题。

我的理解是,当在Lisp中使用树时,我必须使用defun leaf,node,然后方法来构造树,以检索节点和元素以及在开始之前识别它是叶子还是节点的方法构建进一步的功能来搜索树。但问题出现的方式表明我的解决方案过于复杂。

有人可能会让我朝着正确的方向推动我应该做些什么,或建议一个资源来更好地理解这个问题。

提前致谢。

1 个答案:

答案 0 :(得分:1)

您在示例中用于表示树的数据结构是使用cons构建的列表:

? '(((a . b). c) . (d . ((e . f) . g)))
(((A . B) . C) D (E . F) . G)

相同
? (cons (cons (cons 'a 'b) 'c) (cons 'd (cons (cons 'e 'f) 'g)))
(((A . B) . C) D (E . F) . G)

但是,您可以使用不同的表示形式,例如使用defstruct构造的结构。因此,创建抽象函数来构造树,提取左和右,以及测试节点和叶子是有意义的。

对于列表,您可以使用:

(defun mktree (left right) (cons left right))
(defun nodep (tree) (consp tree))
(defun leafp (tree) (atom tree))
(defun left  (tree) (car tree))
(defun right (tree) (cdr tree))

? (mktree (mktree (mktree 'a 'b) 'c) (mktree 'd (mktree (mktree 'e 'f) 'g)))
(((A . B) . C) D (E . F) . G)

而对于结构,定义如下:

(defstruct (btree) left right)
(defun mktree (left right) (make-btree :left left :right right))
(defun nodep (tree) (btree-p tree))
(defun leafp (tree) (not (nodep tree)))
(defun left  (tree) (btree-left tree))
(defun right (tree) (btree-right tree))

? (mktree (mktree (mktree 'a 'b) 'c) (mktree 'd (mktree (mktree 'e 'f) 'g)))
#S(BTREE :LEFT #S(BTREE :LEFT #S(BTREE :LEFT A :RIGHT B) :RIGHT C) :RIGHT #S(BTREE :LEFT D :RIGHT #S(BTREE :LEFT #S(BTREE :LEFT E :RIGHT F) :RIGHT G)))

无论哪种方式,您的searchtree函数都可以以与您的表示无关的方式编写:

(defun searchtree (atm tree)
  (labels
      ((sub (tree res)
         (cond
          ((nodep tree) 
           (sub (left  tree) (cons 'left  res))
           (sub (right tree) (cons 'right res)))
          ((leafp tree)
           (when (eql atm tree)
             (return-from searchtree (reverse res)))))))
    (sub tree nil)))

所以不管你的代表什么,你都会得到

? (searchtree 'b (mktree (mktree (mktree 'a 'b) 'c) (mktree 'd (mktree (mktree 'e 'f) 'g))))
(LEFT LEFT RIGHT)