append([],Xs,Xs).
append([Head|Tail],List2,[Head|Tail2]):-
append(Tail,List2,Tail2).
上部追加方法将前两个参数槽中的元素添加到第三个参数变量。
?-append([2,1], [3,4], X).
?-X=[2,1,3,4]
我在步骤中看到的方式是(这是错误的) - >
追加([1],[3,4],X)
追加(1 | [],[3,4],1 | X)
就是这样。我无法理解它如何将元素加在一起,这就是我可以使用的帮助 - 这个方法如何工作的清晰解释。我只是不明白[2,1]数组如何被添加到最终结果中。
答案 0 :(得分:3)
如果您在跟踪中重命名,则递归中的X
与原始调用中的X
不同
append(2 | [1], [3,4], 2 | X1) -- X = [2|X1]
append([1], [3,4], X1)
append(1 | [], [3,4], 1 | X2) -- X1 = [1|X2]
append ([], [3,4], [3,4]) -- X2 = [3,4]
所以X1 = [1,3,4]
和X = [2,1,3,4]
答案 1 :(得分:1)
首先,您必须了解如何在Prolog中实现列表。它本质上是递归的数据结构。
[]
表示。非空列表由结构./2
表示,由列表的 head (prolog术语)和尾部(另一个列表,包括保存第一个的所有项目)。所以......
[]
- 零项目列表,表示为[]
[a]
- 1个项目的列表,表示为.(a,[])
[a,b]
- 包含2个项目的列表,表示为.(a,.(b,[]))
[a,b,c]
- 包含3个项目的列表,表示为.(a,.(b,.(c,[])))
使用方括号的标准列表符号只是在此表示之上的语法糖。说[Head|Tail]
是一种礼貌的方式说.(Head,Tail)
并说[X,Y,Z|More]
是礼貌的说.(X,.(Y,.(Z,More)))
的方式。 (你可能会注意到某个...... Lisp-ishness ...到这里的内部列表符号。)
了解如何表示列表,将一个列表附加(连接)到另一个列表的天真算法是:
首先,需要考虑两个特殊情况:
将非空列表X附加到空列表Y的结果为X.
将[1,2,3]
附加到[]
并获取{ {1}}。注意。 但是,这种情况可以(通常)由下面的普通情况处理。这是优化的机会,因为在整个列表中递归是没有意义的,只是在最后用[1,2,3]
替换[]
,对吗?
将空列表X附加到非空列表Y的结果为Y.
将[]添加到[1,2,3]并获得{ {1}}。
否则,我们有一般情况:
将非空列表Y附加到非空列表X以生成列表Z。要做到这一点很简单:
我们简单地在列表X上进行递归,在我们前进的时候弹出它的头部,并在前面列出Z,结果。您会注意到,当发生这种情况时,列表Z是一个损坏的列表结构,因为它的最后一个节点始终是未绑定的而不是[]
。当源列表列表X耗尽并退化为空列表的特殊情况时,这将在最后修复。此时,未绑定的最后一个节点在与列表Y(零个或多个节点的列表)统一时被绑定,为我们留下了正确的列表结构。
[1,2,3]
的Prolog代码直接表达此算法。如前所述,第一个子句是可选的优化,因为它可以由第3个子句(普通情况)处理。但是,它需要削减,因为没有,回溯会产生两种解决方案。
[]