Prolog:使用最后一个元素作为枢轴(无限循环)的快速排序

时间:2017-04-12 19:30:15

标签: prolog quicksort

我正在尝试使用最后一个元素作为数据集在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/4lastElement/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_).

1 个答案:

答案 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的调用。