Prolog逆转列表 - 快速方法

时间:2018-03-11 07:53:24

标签: list prolog

我试图编写代码以反转Prolog中的列表。

我的工作成果是:

reverse(X,X).
reverse([X|Y],[H|X]):-
    reverse(Y,H).

我在prolog上运行了这段代码,但它不起作用。 事实似乎对我来说是正确的,我无法找到错误。 你能救我吗?

1 个答案:

答案 0 :(得分:2)

我的方法使用一个空的累加器列表(如注释中的joel76所述),它以一个接一个的相反顺序填充列表元素。

%  reverse/2
%  reverse(List,Result)
%  
%  Result will be the reversed list that gets returned
reverse(List,Result) :-
    % call the accumulator method with the list and an empty placeholder list
    reverse(List,[],Result).

%  reverse/3
%  reverse(List,Accumulator,ReverseList)
%  
%  >> stop rule for recursion
%  -- checks whether initial List is empty (aka the reversing process is done)
%  -- returns the ReversedList if completed, otherwise carry ReverseList over throughout the next iteration
reverse([],ReversedList,ReversedList).

% actual reversing method
reverse([Head|Tail],RestTail,ReverseList) :-
     reverse(Tail,[Head|RestTail],ReverseList).

在SWI中执行这些语句时,例如reverse([a,b,c,d],X).,其背后的想法变得更加清晰:

 ?- reverse([a,b,c,d],X).
     Call: (7)  reverse([a,b,c,d],          _G2273) ?
     Call: (8)  reverse([a,b,c,d],[],       _G2273) ?
     Call: (9)  reverse(  [b,c,d],[a],      _G2273) ?
     Call: (10) reverse(    [c,d],[b,a],    _G2273) ?
     Call: (11) reverse(      [d],[c,b,a],  _G2273) ?
     Call: (12) reverse(       [],[d,c,b,a],_G2273) ?
     Exit: (12) reverse(       [],[d,c,b,a],[d,c,b,a]) ?
     Exit: (11) reverse(      [d],[c,b,a],  [d,c,b,a]) ?
     Exit: (10) reverse(    [c,d],[b,a],    [d,c,b,a]) ?
     Exit: (9)  reverse(  [b,c,d],[a],      [d,c,b,a]) ?
     Exit: (8)  reverse([a,b,c,d],[],       [d,c,b,a]) ?
     Exit: (7)  reverse([a,b,c,d],          [d,c,b,a]) ?
 X = [d,c,b,a].

说明:想象一下,初始列表是一堆元素。通过像[Head|Tail]这样的列表拆分,每个初始列表的元素都会自行删除。通过创建新列表Head[Head|ReverseTail]将添加到累加器列表中。 RevserseTail只是累加器列表的当前内容,因此当前反向列表获得在第一个位置添加的初始列表Head,而尾部跟在之后。以下步骤将递归调用reverse / 3,其中Tail部分作为初始列表的剩余部分,[Head|ReverseTail]作为当前反向列表,ReverseList没有其他目的其他目的而不是作为过程结束时返回的值。

这将重复进行,直到初始列表的所有元素逐个添加到累加器并且初始列表为空,即递归停止并返回反向列表。