(defun mergl(l1 l2 l3)
(cond
((and (null l1) (not(null l2))) l2)
((and (null l2) (not(null l1))) l1)
((and (null l1) (null l2)) l3)
((< (car l1) (car l2)) (setf l3 (cons (car l1) l3)) (mergl (cdr l1) l2 l3) l3)
(t (setf l3 (cons (car l2) l3)) (mergl l1 (cdr l2) l3) l3)
)
)
上面的代码应该采用2个列表并合并它们。但由于某种原因,它似乎拒绝做递归部分。我在这里缺少什么?(我知道append
会这样做但我可以不使用它)
(mergl '(1 3 5 7) '(2 4 6 8) '())
,结果为(1)
答案 0 :(得分:4)
简单地添加(format t "~a ~a ~a~%" l1 l2 l3)
作为您程序的第一种形式是有帮助的;结果将是:
(1 3 5 7) (2 4 6 8) NIL
(3 5 7) (2 4 6 8) (1) <-- this will be interesting later
(3 5 7) (4 6 8) (2 1)
(5 7) (4 6 8) (3 2 1)
(5 7) (6 8) (4 3 2 1)
(7) (6 8) (5 4 3 2 1)
(7) (8) (6 5 4 3 2 1)
NIL (8) (7 6 5 4 3 2 1)
(1) <-- oops what happened?
错误发生在最后; l1
为null
,因此您只需返回l2
- 或者您认为。但是,由于另一个错误(您的代码 - 我的格式),您返回的结果不是l1
,l2
或l3
:
((< (car l1) (car l2))
(setf l3 (cons (car l1) l3))
(mergl (cdr l1) l2 l3)
l3)
(t
(setf l3 (cons (car l2) l3))
(mergl l1 (cdr l2) l3)
l3)))
在递归调用mergl
之后,你扔掉了结果,在展开返回堆栈之后,你最终将{strong>第一个值setf
l3
返回到在这种情况下恰好是(1)
。它是l3
的第一个值,因为每个递归调用在输入过程时都会分配一个新的l3
,因此后来的l3
调用尚未修改第一个setf
。 / p>
我想这应该是一个带有累加器的尾递归过程,应该像这样编写:
(defun mergl (l1 l2 l3)
(cond
((and (null l1) (null l2))
(reverse l3))
((null l1)
(mergl l1 (cdr l2) (cons (car l2) l3)))
((null l2)
(mergl (cdr l1) l2 (cons (car l1) l3)))
((< (car l1) (car l2))
(mergl (cdr l1) l2 (cons (car l1) l3)))
(t
(mergl l1 (cdr l2) (cons (car l2) l3)))))
然后
(mergl '(1 3 5 7) '(2 4 6 8) '())
=> (1 2 3 4 5 6 7 8)
功能代码是重复的,可以简化为:
(defun mergl (l1 l2 l3)
(cond
((and (null l1) (null l2))
(reverse l3))
((or (null l2) (and (not (null l1)) (< (car l1) (car l2))))
(mergl (cdr l1) l2 (cons (car l1) l3)))
(t
(mergl l1 (cdr l2) (cons (car l2) l3)))))