(SWI)Prolog中的快速反向排序

时间:2010-11-15 18:35:55

标签: sorting prolog

我正在寻找一种在Prolog中以相反顺序对列表进行排序的快速方法。从算法来看,它的执行速度应该与标准排序一样快,但由于显而易见的原因,我提出的选项要慢得多。

谓词rsort1/2排序然后反转。

rsort1(L1, L2) :-
    sort(L1, Tmp),
    reverse(Tmp, L2).

谓词rsort2/2使用predsort/3和自定义比较器。

rsort2(L1, L2) :-
    predsort(reverse_compare, L1, L2).

reverse_compare(Delta, E1, E2) :-
    compare(Delta, E2, E1).

为了测试他们的表现,我已经生成了一个巨大的随机列表:

?- Size = 1234567,
   findall(N, (between(1, Size, _), N is random(Size)), Ns),
   assert(test_list(Ns)).
Size = 1234567,
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258|...].

这些是标准sort的运行时:

?- test_list(Ns), time(sort(Ns, NsS)).
% 2 inferences, 7.550 CPU in 8.534 seconds (88% CPU, 0 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [0, 1, 3, 5, 8, 10, 12, 14, 16|...].

...代表rsort1

?- test_list(Ns), time(rsort1(Ns, NsS)).
% 779,895 inferences, 8.310 CPU in 9.011 seconds (92% CPU, 93850 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [1234564, 1234563, 1234562, 1234558, 1234557, 1234556, 1234555|...].

...以及rsort2

?- test_list(Ns), time(rsort2(Ns, NsS)).
% 92,768,484 inferences, 67.990 CPU in 97.666 seconds (70% CPU, 1364443 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [1234564, 1234563, 1234562, 1234558, 1234557, 1234556, 1234555|...].

我可以比rsort1rsort2速度更好吗?

2 个答案:

答案 0 :(得分:3)

如果您正在进行可移植的排序例程(即使用PROLOG定义),那么您可能无法更快地实现任何操作(或者需要更快地执行排序顺序)谓词,用C / C ++本机执行排序例程,例如sort/2msort/2

如果速度是最重要的问题,你当然可以使用外部定义编写自己的非可移植谓词来进行反向排序。例如,可以使用SWI-PL C++ interface(参见那里的示例)来编写rsort/2的C ++定义,也许使用也在C ++中实现的comparison predicates

同样,您也可以使用SWI-PL C接口在C中编写rsort/2。 SWI-PROLOG源中的src/pl-list.c包含用于nat_sort()sort/2msort/2的排序方法(即keysort/2)的实现。要实施rsort/2,您可能只需要遵循其实施并调整/撤销对compare()的调用的解释,该调用描述了术语的标准顺序。

答案 1 :(得分:-1)

定义谓词:
1.获取列表中的最小数字。
2.删除列表中的项目。
3.合并两个列表。
4.按列表排序列表 a)得到最低的
b)删除列表中的最低位
c)对没有最低(递归)的新列表进行排序 使用基本规则订单列表([X],[X])。