首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Prolog中高效地添加3份列表?

如何在Prolog中高效地添加3份列表?
EN

Stack Overflow用户
提问于 2015-05-07 20:50:54
回答 3查看 3.5K关注 0票数 4

我知道如何处理两份清单:

代码语言:javascript
复制
append([],L,L).
append([H|T],L,[H|R]):-append(T,L,R).

但是怎么做三次呢?不对两个列表使用附加项两次。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-05-07 21:22:13

若要有效地追加列表,请考虑使用差异列表。差异列表是使用带有两个列表的术语表示的列表。最常见的表示形式使用(-)/2作为术语的函子。例如,列表[1,2,3]可以表示为:

代码语言:javascript
复制
[1,2,3| Tail]-Tail.

通过跟踪列表尾,即它的开放端,您可以高效地执行几个操作。例如,可以通过实例化尾将元素追加到O(1)中列表的末尾:

代码语言:javascript
复制
add_to_end_of_list(List-Tail, Element, List-Tail2) :-
    Tail = [Element| Tail2].

或者简单地说:

代码语言:javascript
复制
add_to_end_of_list(List-[Element| Tail2], Element, List-Tail2).

我们试试看:

代码语言:javascript
复制
?- add_to_end_of_list([1,2,3| Tail]-Tail, 4, Result).
Tail = [4|_G1006],
Result = [1, 2, 3, 4|_G1006]-_G1006.

现在,附加两个列表是相似的,也是O(1)。我们不需要追加一个元素,而是添加一个元素列表:

代码语言:javascript
复制
dappend(List1-Tail1, Tail1-Tail2, List1-Tail2).

例如:

代码语言:javascript
复制
?- dappend([1,2,3 | Tail1]-Tail1, [4,5,6| Tail2]-Tail2, Result).
Tail1 = [4, 5, 6|Tail2],
Result = [1, 2, 3, 4, 5, 6|Tail2]-Tail2.

我留给你一个练习,用不同的列表来回答你自己的问题。注意,从一个不同的列表到一个封闭的列表,只是一个实例化开放端到空列表的问题。例如:

代码语言:javascript
复制
?- dappend([1,2,3 | Tail1]-Tail1, [4,5,6| Tail2]-Tail2, Result-[]).
Tail1 = [4, 5, 6],
Tail2 = [],
Result = [1, 2, 3, 4, 5, 6].

但是,从封闭列表到差异列表确实需要遍历列表,即O(n):

代码语言:javascript
复制
as_difflist([], Back-Back).
as_difflist([Head| Tail], [Head| Tail2]-Back) :-
    as_difflist(Tail, Tail2-Back).

当然,构建不同列表的成本可能是问题,也可能不是问题,这取决于如何获得初始列表以及在应用程序中附加列表的频率。

票数 5
EN

Stack Overflow用户

发布于 2015-05-07 20:57:23

代码语言:javascript
复制
append3(Xs, Ys, Zs, XsYsZs) :-
   append(Xs, YsZs, XsYsZs),
   append(Ys, Zs, YsZs).

尽可能的高效。“成本”是关于“Xs|+|Ys”的“推论”。但是,您可能会尝试像下面这样定义它,并使用大约2欧元(Xs|+|Ys)的推断。

代码语言:javascript
复制
append3bad(Xs, Ys, Zs, XsYsZs) :-
   append(Xs, Ys, XsYs),
   append(XsYs, Zs, XsYsZs).

另外,终止是第一种情况要好得多

代码语言:javascript
复制
append3(Xs, Ys, Zs, XsYsZs)
   terminates_if b(Xs),b(Ys);b(XsYsZs)

意味着需要知道XsYsXsYsZs使append3/4终止.对比

代码语言:javascript
复制
append3bad(Xs, Ys, Zs, XsYsZs)
   terminates_if b(Xs),b(Ys);b(Xs),b(XsYsZs)
                             ^^^^^

对于append3bad/4XsYsZs是不够的,而且还必须知道Xs

票数 4
EN

Stack Overflow用户

发布于 2015-05-07 21:37:11

希望我能理解这个问题(我不认为下面的解决方案比这里的其他解决方案更有效),但是你的意思是这样的吗?

代码语言:javascript
复制
append([],[],L,L).
append([],[H|T],L,[H|R]) :- append([],T,L,R).
append([H|T],L0,L1,[H|R]) :- append(T,L0,L1,R).
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30111397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档