需要帮助理解prolog方法以附加列表元素

时间:2011-09-25 20:07:08

标签: list prolog

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. 追加(2 | [1],[3,4],2 | X)
  2. 追加([1],[3,4],X)

  3. 追加(1 | [],[3,4],1 | X)

  4. 追加([],[3,4],[3,4])
  5. 就是这样。我无法理解它如何将元素加在一起,这就是我可以使用的帮助 - 这个方法如何工作的清晰解释。我只是不明白[2,1]数组如何被添加到最终结果中。

2 个答案:

答案 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个子句(普通情况)处理。但是,它需要削减,因为没有,回溯会产生两种解决方案。

[]