【问题标题】:transforming trees in lisp在 lisp 中转换树
【发布时间】:2016-03-14 22:07:15
【问题描述】:

我正在尝试从 (A (B) (C (D) (E))) 中的 (A 2 B 0 C 2 D 0 E 0) 修改树的表示。我的代码是这样的:

(defun transform(l)
 (cond
   ( (null l) NIL)
   ( (and (not (numberp (car l))) (= (cadr l) 0) (null (cddr l)))
        (cons (car l) '(NIL NIL) ))  
   ( (and (not (numberp (car l))) (= (cadr l) 0))
       (cons (cons (car l) '(NIL NIL) ) (list (transform (cddr l))))) 
   ( (not (numberp (car l))) 
         (cons (car l) (list (transform (cddr l)))))
   ( T (transform (cdr l)))
 ))

 (defun subarbst(l nr)
 (cond
    ( (= nr 0) nil)
    ( (atom l) l)
    ( ( numberp (car l)) (cons (car l) (subarbst (cdr l) nr)))
    ( (and (= nr 1) (= (cadr l) 0)) (list (car l) (cadr l))) 
    ( T (cons (car l) (subarbst (cdr l) (+ (car (cdr l)) (- nr 1)))))
)
) 

 (defun subarbdr(l nr)
 (cond 
   ( (= nr 1) (subarbst l nr))
   ( (atom l) l)
   ( T (subarbdr (cddr l) (+ (car (cdr l)) (- nr 1))))
 )
)

(defun transf(l)
(cond 
  ( (null l) nil)
  ( (= 0 (cadr l)) (cons (car l) '(nil nil)))
  ( (= 1 (cadr l)) (list (car l) (transf (subarbst (cddr l) '1))))
  ( (= 2 (cadr l)) (list (car l)
                       (transf (subarbst (cddr l) '1))
                       (transf (subarbdr (cddr l) '2))))
))

但是,我得到的不是第二种形式,而是:(A(B NIL NIL)(C(D NIL NIL)(E NIL NIL))),谁能告诉我为什么我会得到那些“NIL”价值观? .. 提前谢谢!

【问题讨论】:

    标签: tree lisp common-lisp


    【解决方案1】:

    https://stackoverflow.com/a/34193414/1250772 对此给出了答案,作为对显然正在解决相同家庭作业问题的用户的回应的一部分。该解决方案基于将前缀表示法反转为后缀,然后将其解释为基于堆栈的反向波兰表示法以构建树。

    巧合的是,该答案中的以下代码会产生与您所要求的相同的表示形式。为了解决该问题中的中序遍历问题,我即兴提出了该表示:

    (defun build-tree (syntax)
      (let ((rs (reverse syntax))
            (stack))
        (dolist (item rs (pop stack))  ;; heart of the interpreter loop
          (cond ((integerp item) (push item stack))  ;; integer instruction
                ((symbolp item) (let ((num (pop stack)))  ;; sym instruction
                                  ;; construct node using backquote, and
                                  ;; put it on the stack.
                                  (push `(,item ,@(loop repeat num
                                                        collect (pop stack)))
                                        stack)))))))
    

    【讨论】:

      【解决方案2】:

      这是一个可能的解决方案,其中使用了一个辅助函数tree-sequence。请注意,这些函数不会检查输入列表的有效性。

      main函数的结构非常简单:

      (defun transform(l)
        (if (null l)
            nil
            (tree-sequence l)))
      

      而辅助函数基于以下思想:在每次调用时,将要转换的列表的其余部分传递给函数,该函数返回一对值:

      1. 已经被函数转化的树,

      2. 列表的其余部分用于构建第一个值的列表部分。

      这样,在每一个递归步骤,函数本身可以使用第二个值继续变换树。

      函数如下:

      (defun tree-sequence(l)
        (case (cadr l)
          (0 (values (list (car l)) (cddr l)))
          (1 (multiple-value-bind (left-subtree rest-of-list) (tree-sequence (cddr l))
                (values (list (car l) left-subtree) rest-of-list)))
          (t (multiple-value-bind (left-subtree rest-of-list) (tree-sequence (cddr l))
                (multiple-value-bind (right-subtree rest-of-rest) (tree-sequence rest-of-list)
                   (values (list (car l) left-subtree right-subtree) rest-of-rest))))))
      

      请注意,返回的这两个值仅在函数tree-sequence 中使用,而transform 仅使用返回的第一个值,即树。

      最后,请注意,这种方法适用于作为树节点的任何类型的元素,包括整数。

      【讨论】:

        猜你喜欢
        • 2015-05-06
        • 1970-01-01
        • 2010-10-27
        • 1970-01-01
        • 1970-01-01
        • 2014-09-03
        • 1970-01-01
        • 1970-01-01
        • 2011-08-03
        相关资源
        最近更新 更多