其实你已经很接近了。看看这个踪迹:
?- trace, merge([1,3,5,6], [2,4,7,8], X).
Call: (9) merge([1, 3, 5, 6], [2, 4, 7, 8], _6684) ? creep
Call: (10) 1=<2 ? creep
Exit: (10) 1=<2 ? creep
Call: (10) _7050=[1|_6684] ? creep
Exit: (10) [1|_6684]=[1|_6684] ? creep
Call: (10) merge([3, 5, 6], [2, 4, 7, 8], [1|_6684]) ? creep
Call: (11) 3=<2 ? creep
Fail: (11) 3=<2 ? creep
Redo: (10) merge([3, 5, 6], [2, 4, 7, 8], [1|_6684]) ? creep
Call: (11) _7062=[2, 1|_6684] ? creep
Exit: (11) [2, 1|_6684]=[2, 1|_6684] ? creep
Call: (11) merge([3, 5, 6], [4, 7, 8], [2, 1|_6684]) ? creep
Call: (12) 3=<4 ? creep
Exit: (12) 3=<4 ? creep
Call: (12) _7074=[3, 2, 1|_6684] ? creep
Exit: (12) [3, 2, 1|_6684]=[3, 2, 1|_6684] ? creep
Call: (12) merge([5, 6], [4, 7, 8], [3, 2, 1|_6684]) ? creep
Call: (13) 5=<4 ? creep
Fail: (13) 5=<4 ? creep
Redo: (12) merge([5, 6], [4, 7, 8], [3, 2, 1|_6684]) ? creep
Call: (13) _7086=[4, 3, 2, 1|_6684] ? creep
Exit: (13) [4, 3, 2, 1|_6684]=[4, 3, 2, 1|_6684] ? creep
Call: (13) merge([5, 6], [7, 8], [4, 3, 2, 1|_6684]) ? creep
Call: (14) 5=<7 ? creep
Exit: (14) 5=<7 ? creep
Call: (14) _7098=[5, 4, 3, 2, 1|_6684] ? creep
Exit: (14) [5, 4, 3, 2, 1|_6684]=[5, 4, 3, 2, 1|_6684] ? creep
Call: (14) merge([6], [7, 8], [5, 4, 3, 2, 1|_6684]) ? creep
Call: (15) 6=<7 ? creep
Exit: (15) 6=<7 ? creep
Call: (15) _7110=[6, 5, 4, 3, 2, 1|_6684] ? creep
Exit: (15) [6, 5, 4, 3, 2, 1|_6684]=[6, 5, 4, 3, 2, 1|_6684] ? creep
在递归深度的这一刻,你几乎有了解决方案。然后它开始出错:
Call: (15) merge([], [7, 8], [6, 5, 4, 3, 2, 1|_6684]) ? creep
Fail: (15) merge([], [7, 8], [6, 5, 4, 3, 2, 1|_6684]) ? creep
Redo: (14) merge([6], [7, 8], [5, 4, 3, 2, 1|_6684]) ? creep
Fail: (14) merge([6], [7, 8], [5, 4, 3, 2, 1|_6684]) ? creep
Redo: (13) merge([5, 6], [7, 8], [4, 3, 2, 1|_6684]) ? creep
Fail: (13) merge([5, 6], [7, 8], [4, 3, 2, 1|_6684]) ? creep
Redo: (12) merge([5, 6], [4, 7, 8], [3, 2, 1|_6684]) ? creep
Fail: (12) merge([5, 6], [4, 7, 8], [3, 2, 1|_6684]) ? creep
Redo: (11) merge([3, 5, 6], [4, 7, 8], [2, 1|_6684]) ? creep
Fail: (11) merge([3, 5, 6], [4, 7, 8], [2, 1|_6684]) ? creep
Redo: (10) merge([3, 5, 6], [2, 4, 7, 8], [1|_6684]) ? creep
Fail: (10) merge([3, 5, 6], [2, 4, 7, 8], [1|_6684]) ? creep
Redo: (9) merge([1, 3, 5, 6], [2, 4, 7, 8], _6684) ? creep
Fail: (9) merge([1, 3, 5, 6], [2, 4, 7, 8], _6684) ? creep
那么您的代码有什么问题?主要有两件事:您正在构建反转的结果(并不少见)并且您没有很好的方法将其传回。安排一个结果变量当然是处理这些问题的一种方法,类似于 Luai 的想法:
merge(X,Y,Z) :- merge(X, Y, [], Z).
merge([H1|T1],[H2|T2],List,NewList):-
(
H1 =< H2 ->
merge(T1,[H2|T2],[H1|List],NewList)
;
merge([H1|T1],T2,[H2|List],NewList)
).
merge([],R,LRev,Res) :- reverse(LRev, L), append(L,R,Res).
merge(R,[],LRev,Res) :- reverse(LRev, L), append(L,R,Res).
或者你将不得不想出另一种方法来做到这一点,例如传递列表的尾部,如下所示:
merge2([H1|T1], [H2|T2], MT) :-
(H1 =< H2 ->
MT=[H1|MT2],
merge2(T1, [H2|T2], MT2)
;
MT=[H2|MT2],
merge2([H1|T1], T2, MT2)
).
merge2([], T2, T2).
merge2(T2, [], T2).
我个人更喜欢这种方法。