我正在尝试使用最后一个元素作为数据集在Prolog中实现Quicksort但不知何故我的谓词进入无限循环。我正在使用累加器来确定到目前为止排序的部分(最终应该等于它应该查找的排序列表S)。
quicksort([], S, S).
quicksort(L, S, A ) :-
lastElement(L, P), /*last element P as pivot*/
split(L, P, Greater, Smaller), /* splits L into set Greater (than) and Smaller (than) by pivot P */
quicksort(Greater, Greater_S, A), /* require Greater to be sorted as well, calling this Greater_S */
quicksort(Smaller, S, [P|Greater_S]). /* same for Smaller, but accumulator should already have P and Greater_S sorted -> [P|Greater_S] as accumulator */
quicksort(L, S) :-
quicksort(L, S, []).
quicksort(G, G_S, A)
以某种方式,列表G_S
似乎使用相同的元素迭代地增加了大小,即[X, X, X, X, ...]
。
我做错了什么?
如果有人能帮助我,我会非常感激!
提前致谢。
编辑:谓词split/4
和lastElement/2
的定义:
lastElement([X], X).
lastElement([_|T], X) :- lastElement(T, X).
split([], _, [], []).
split([H|T], P, G, K) :-
H > P,
G = [H|T_],
split(T, P, T_, K).
split([H|T], P, G, K) :-
H =< P,
K = [H|T_],
split(T, P, G, T_).
答案 0 :(得分:2)
以下答案;但是请将原始版本与“最后一个元素作为支点”版本进行比较,您将看到“最后一个元素作为支点”只是愚蠢。在问题陈述中某处可能存在我们都缺失的问题吗?
在我看来,如果你使用更简单的Quicksort实现作为起点,你的生活会更容易。来自Prolog wiki page
partition([], _, [], []).
partition([X|Xs], Pivot, Smalls, Bigs) :-
( X @< Pivot ->
Smalls = [X|Rest],
partition(Xs, Pivot, Rest, Bigs)
; Bigs = [X|Rest],
partition(Xs, Pivot, Smalls, Rest)
).
quicksort([]) --> [].
quicksort([X|Xs]) -->
{ partition(Xs, X, Smaller, Bigger) },
quicksort(Smaller), [X], quicksort(Bigger).
您必须使用phrase
:
quicksort(List, Sorted) :- phrase(quicksort(List), Sorted).
现在它排序了:
?- quicksort([c,b,a,b], S).
S = [a, b, b, c].
您唯一需要改变的是取最后一个元素而不是第一个元素,可能在quicksort//1
的第二个子句中,如下所示:
quicksort([X|Xs]) -->
{ append(Front, [Pivot], [X|Xs]),
partition(Front, Pivot, Smaller, Bigger)
},
quicksort(Smaller), [Pivot], quicksort(Bigger).
这种append/3
的使用留下了一个选择点;您可以根据需要编写自己的list_front_last/3
,或使用
once( append(...) )
希望有所帮助。
编辑:
您可以稍微改变lastElement
的实现:
list_front_last([], Last, [], Last).
list_front_last([X|Xs], X0, [X0|Front], Last) :-
list_front_last(Xs, X, Front, Last).
您已经解压缩quicksort//1
:
quicksort([X|Xs]) --> ...
所以你可以直接使用
list_front_last(Xs, X, Front, Pivot)
而不是对append/3
的调用。