了解prolog中quicksort的运行轨迹

时间:2014-10-30 08:50:06

标签: sorting prolog quicksort trace

我有快速排序的以下prolog代码:

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).

split(X,[],[],[]).
split(X,[Y|Tail],[Y|Small],Big):-
    gt(X,Y),
    !,
    split(X,Tail,Small, Big).

split(X,[Y|Tail],Small,[Y|Big]):-
    split(X,Tail,Small,Big).

例如,数组是[3,2,4,1,5]。快速排序([3,2,4,1,5],排序)。我需要了解程序的运行轨迹。我差点做,但有一点我不知道:(这只是跟踪的一部分):

Redo: (11) split(3, [5], _G3785, _G3782) ? creep
Call: (12) split(3, [], _G3785, _G3788) ? creep
Exit: (12) split(3, [], [], []) ? creep
Exit: (11) split(3, [5], [], [5]) ? creep
Exit: (10) split(3, [1, 5], [1], [5]) ? creep
Exit: (9) split(3, [4, 1, 5], [1], [4, 5]) ? creep
Exit: (8) split(3, [2, 4, 1, 5], [2, 1], [4, 5]) ? creep

为什么我们退出:(11)分裂(3,[5],[],[5])?在第11行爬行,5来自哪里? 有人可以帮帮我!我真的很感激。

2 个答案:

答案 0 :(得分:2)

我们将此作为参考:

[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).

我们将关注您的跟踪片段。

Redo: (11) split(3, [5], _G3785, _G3782) ? creep

此重做是由于原始查询中的子句[2]失败(未显示,在跟踪之前),因为gt(3,5)为false。然后Redo将导致查询第[3]条。我们将替换已知的实例化变量,并查看第3个子句查询的内容:

[A] split(3, [5|[]], Small, [5|Big]) :- split(3, [], Small, Big)

这会导致下一条跟踪线,其中_G3785Small,而_G3788Big

Call: (12) split(3, [], _G3785, _G3788) ? creep

这将在第一个子句[1]上成功并产生跟踪的这一部分:

Exit: (12) split(3, [], [], []) ? creep

由于这是在上面的执行条款[3]中(如[A]所示),因此现在Small已使用[]和{{1}实例化,因此产生以下结果与Big

[]

换句话说,执行[A]中显示的第三个子句会导致:

split(3, [5|[]], [], [5|[]])

您的下一条跟踪线显示的是:

split(3, [5], [], [5])

答案 1 :(得分:0)

在比较功能分割的规则2后应该有一个切割:

split(X,[Y|Tail],[Y|Small],Big):-
gt(X,Y), 
!,
split(X,Tail,Small, Big).