我试图在(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))),任何人都可以告诉我为什么我会得到那些&#34 ; NIL"值? .. 提前谢谢!
答案 0 :(得分: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)))))))
答案 1 :(得分:0)
这是一种可能的解决方案,其中使用了辅助函数tree-sequence
。请注意,这些函数不会检查输入列表的有效性。
主要功能有一个非常简单的结构:
(defun transform(l)
(if (null l)
nil
(tree-sequence l)))
虽然辅助函数基于以下思想:在每次调用时,要转换的列表的其余部分将传递给函数,该函数返回一对值:
由函数
列表的其余部分跟随用于构建第一个值的列表部分。
这样,在每个递归步骤中,函数本身可以使用第二个值继续转换树。
这是功能:
(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
仅使用返回的第一个值,即树。
最后,请注意,此方法适用于任何类型的元素作为树的节点,包括整数。