我正在寻找一种在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|...].
我可以比rsort1
和rsort2
速度更好吗?
答案 0 :(得分:3)
如果您正在进行可移植的排序例程(即使用PROLOG定义),那么您可能无法更快地实现任何操作(或者需要更快地执行排序顺序)谓词,用C / C ++本机执行排序例程,例如sort/2
或msort/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/2
和msort/2
的排序方法(即keysort/2
)的实现。要实施rsort/2
,您可能只需要遵循其实施并调整/撤销对compare()
的调用的解释,该调用描述了术语的标准顺序。
答案 1 :(得分:-1)
定义谓词:
1.获取列表中的最小数字。
2.删除列表中的项目。
3.合并两个列表。
4.按列表排序列表
a)得到最低的
b)删除列表中的最低位
c)对没有最低(递归)的新列表进行排序
使用基本规则订单列表([X],[X])。