我之前有关于此快速排序here的问题。快速排序的序言代码:
gt(X,Y):- X @>Y.
conc([],List, List).
conc([Head|Tail], List1, [Head|List2]):- conc(Tail, List1, List2).
quicksort([],[]).
quicksort([X|Tail],Sorted):-
split(X,Tail,Small,Big),
quicksort(Small,SortedSmall),
quicksort(Big,SortedBig),
conc(SortedSmall,[X|SortedBig],Sorted).
[1]split(X,[],[],[]).
[2]split(X,[Y|Tail],[Y|Small],Big):-
gt(X,Y),!,
split(X,Tail,Small,Big).
[3]split(X,[Y|Tail],Small,[Y|Big]):-
split(X,Tail,Small,Big).
例如,数组是[3,2,4,1,5]。这是跟踪路线的第一部分:
?- trace, quicksort([3,2,4,1,5], Sorted).
1 Call: (7) quicksort([3, 2, 4, 1, 5], _G4136) ? creep
2 Call: (8) split(3, [2, 4, 1, 5], _G4269, _G4270) ? creep
3 Call: (9) gt(3, 2) ? creep
4 Call: (10) 3@>2 ? creep
5 Exit: (10) 3@>2 ? creep
6 Exit: (9) gt(3, 2) ? creep
7 Call: (9) split(3, [4, 1, 5], _G4261, _G4273) ? creep
8 Call: (10) gt(3, 4) ? creep
9 Call: (11) 3@>4 ? creep
10 Fail: (11) 3@>4 ? creep
11 Fail: (10) gt(3, 4) ? creep
12 Redo: (9) split(3, [4, 1, 5], _G4261, _G4273) ? creep
13 Call: (10) split(3, [1, 5], _G4261, _G4264) ? creep
在第2行,prolog应用了split的规则[2],我们有Call: (8) split(3, [2, 4, 1, 5], _G4269, _G4270)
,我们_G4269
为[2|Small]
,_G4270
为{{1} }。
然后比较3和2,Big
返回true并且不执行剪切。继续使用gt(3,2)
split(X,Tail,Small,Big)
如果Call: (9) split(3, [4, 1, 5], _G4261, _G4273)
返回false,prolog将执行剪切,然后应用分割的规则[3](第11-12行)。
我做对了,为什么最后一个变量变成了新变量(gt(X,Y)
而不是_G4237
)?因为在代码中我认为它是相同的。
任何人都可以帮我解决问题吗? 非常感谢!
答案 0 :(得分:0)
准确地说:你的问题涉及这一部分的痕迹:
2 Call: (8) split(3, [2, 4, 1, 5], _G4269, _G4270) ? creep
3 Call: (9) gt(3, 2) ? creep
4 Call: (10) 3@>2 ? creep
5 Exit: (10) 3@>2 ? creep
6 Exit: (9) gt(3, 2) ? creep
7 Call: (9) split(3, [4, 1, 5], _G4261, _G4273) ? creep
对应于对:
的调用split(X,[Y|Tail],[Y|Small],Big):-
gt(X,Y),!,
split(X,Tail,Small,Big).
并且你没有 VISIBLE 获得不同变量的原因,因为使用了相同的变量Big
。我承认这令人困惑。而且,您可以获得相同的变量。这可以显示直接调用split(3, [2, 4, 1, 5], S, B)
跟踪(使用swi v6.6.6):
[trace] ?- split(3, [2, 4, 1, 5], S, B).
Call: (6) split(3, [2, 4, 1, 5], _G4537, _G4538) ? creep
Call: (7) gt(3, 2) ? creep
Call: (8) 3@>2 ? creep
Exit: (8) 3@>2 ? creep
Exit: (7) gt(3, 2) ? creep
Call: (7) split(3, [4, 1, 5], _G4630, _G4538) ? creep
使用相同的变量(_G4538
)。
但是,解释程序可以 INVISIBLE 将变量X
统一为全新的Y
并使用Y
代替X
在后续计算中。这是你的例子中发生的事情。您可以在调试时使用命令g
(目标)来获取回溯,该回溯将显示当前具有当前变量绑定的堆栈跟踪。回到你的例子,当你到达 p>
7 Call: (9) split(3, [4, 1, 5], _G4261, _G4273) ?
键入g
以进行回溯,并获得类似以下内容:
[9] split(3, [4, 1, 5], _G4261, _G4273)
[8] split(3, [2, 4, 1, 5], [2|_G4261], _G4273)
[7] quicksort([3, 2, 4, 1, 5], _G4136)
Call: (9) split(3, [4, 1, 5], _G4261, _G4273) ?
现在你可以看到_G4273
是深度相同的变量[8]和[9]。