是否可以仅使用两个参数来反转列表?

时间:2011-11-08 04:56:25

标签: list prolog

是否可以仅使用两个参数来反转Prolog中的列表?如:

reverse_list(List, Reversed).

这不是家庭作业,我在七周内阅读七种编程语言,我很好奇。

使用三个参数可以使用累加器(很像函数式编程):

reverseList([], Accumulator, Accumulator).
reverseList([Head|Tail], Accumulator, Solution) :-
  reverseList(Tail, [Head|Accumulator], Solution).
reverseList(List, Solution) :-
  reverseList(List, [], Solution).

澄清:我看到了一个附加的解决方案,我想知道你是否可以在没有其他prolog函数的情况下做到这一点

3 个答案:

答案 0 :(得分:5)

确定:

reverseList([[], Accumulator, Accumulator]).
reverseList([[Head|Tail], Accumulator, Solution]) :-
  reverseList([Tail, [Head|Accumulator], Solution]).
reverseList([List, Solution]) :-
  reverseList([List, [], Solution]).

编辑:实际上只有一个:b

非作弊方法:

reverse([],[]).
reverse([H|T],L):-
    reverse(T,R),
    append(R,[H],L).

问题是性能会非常糟糕:你将在列表中进行递归,对于每个元素,你会做一个追加/ 3。 使用时间/ 1和1,000,000个元素的随机列表:

accumulator:    % 2,000,003 inferences, 0.652 CPU in 0.652 seconds (100% CPU, 3066292 Lips)
arity-2         % 1,000,003 inferences, 0.178 CPU in 0.178 seconds (100% CPU, 5602426 Lips)

答案 1 :(得分:3)

您可以使用两个参数编写rev_list函数:

rev_list([], []).
rev_list([Head|Tail], Reversed) :- rev_list(Tail, TailReversed), 
                                       append(TailReversed, [Head], Reversed).

如果它在函数式编程中,你可能更熟悉这个函数:

rev x::xs = rev xs @ [x]

但是,您应该注意到3参数版本是首选版本,因为它是尾递归的。

答案 2 :(得分:2)

我知道我迟到了,但有一种方法可以在不“欺骗”或使用append的情况下做到这一点:

rev([], []).
rev([Head], [Head]).
rev([Head|Tail], [RHead|RTail]) :-
  rev(Tail, [RHead|RMid]),
  rev(RMid, Mid),
  rev([Head|Mid], RTail).

效率不高(O(3^n)时间),但它很优雅,甚至可用于定理证明。