将两个列表追加在一起的 Prolog 算法的说明


这是一种

将两个列表追加在一起的算法:

Domains
list= integer*
Predicates
nondeterm append(list, list, list)
Clauses
append([], List, List) :- !.
append([H|L1], List2, [H|L3]) :- append(L1, List2, L3).
Goal
append([9,2,3,4], [-10,-5,6,7,8], Ot).

结果是一个列表[9,2,3,4,-10,-5,6,7,8],它保存在"Ot"。

我的问题是,这是如何工作的?

我的理解是,在每个递归调用中,在第一个列表中,您只得到尾巴作为列表(因此将其大小减小1直到它被[](,第二个参数"List2"根本没有改变,第三个参数......起初它是[]的,每次递归调用后你都会得到它的尾巴,但由于它是[]的,所以它保持[]

那么,为什么突然在第 3 个参数("Ot"(中我们有了附加列表?有人可以一步一步解释这个算法吗?

首先,让我们将子句翻译成更易于理解的内容:

append([], List, List) :- !.

可以写

append([], List2, Result) :-
    Result = List2,
    !.

append([H|L1], List2, [H|L3]) :- append(L1, List2, L3).

可以写

append(List1, List2, Result) :-
    List1  = [Head1 | Tail1],
    Result = [HeadR | TailR],
    Head1  =  HeadR,
    append(Tail1, List2, TailR).

我希望这对你来说已经更清楚了。

然后,逐步地,

数字指示每次使用的子句,并显示结果调用:

append([9, 2, 3, 4], [-10, -5, 6, 7, 8], Ot).
|
2
|
` append([2, 3, 4], [-10, -5, 6, 7, 8], Ot'). % and Ot = [9|Ot']
  |
  2
  |
  ` append([3, 4], [-10, -5, 6, 7, 8], Ot''). % and Ot' = [2|Ot'']
    |
    2
    |
    ` append([4], [-10, -5, 6, 7, 8], Ot'''). % and Ot'' = [3|Ot''']
      |
      2
      |
      ` append([], [-10, -5, 6, 7, 8], Ot''''). % and Ot''' = [4|Ot'''']
        |
        1
        |
        ` Ot'''' = [-10, -5, 6, 7, 8]

在此步骤中,我们感兴趣的所有值都已定义。请注意结果的头部是如何在随后的(尾递(调用填充其尾部之前设置的 append,以 Prolog 自上而下的方式(也称为"尾递归模缺点"(的特征构建结果列表。

让我们按照定义在最后一步看看Ot是什么:

Ot = [9|Ot']
        Ot' = [2|Ot'']
                 Ot'' = [3|Ot''']
                           Ot''' = [4|Ot'''']
                                      Ot'''' = [-10, -5, 6, 7, 8]
                           Ot''' = [4,          -10, -5, 6, 7, 8]
                 Ot'' = [3,         4,          -10, -5, 6, 7, 8]
        Ot' = [2,        3,         4,          -10, -5, 6, 7, 8]
Ot = [9,       2,        3,         4,          -10, -5, 6, 7, 8]

我希望你能从中得到一些东西。

让我们从Prolog翻译成英语。 我们有两个规则:

  1. 将任何List附加到[]的结果是List .

  2. 将任何List附加到其第一个元素为 H 且余数为 L1 的列表的结果等于其第一个元素也是H的列表,其余数是将List追加到L1的结果。

因此,我们希望将[-10,-5,6,7,8]附加到[9,2,3,4]。 要追加到的列表不为空,因此我们可以跳过该规则。 根据第二条规则,结果9作为第一个元素,后跟将[-10,-5,6,7,8]追加到[2,3,4]的结果。

因此,我们想将[-10,-5,6,7,8]附加到 [2,3,4] . 要追加到的列表不为空,因此我们可以跳过该规则。 根据第二条规则,结果2作为第一个元素,后跟将[-10,-5,6,7,8]追加到[3,4]的结果。

因此,我们希望将[-10,-5,6,7,8]附加到[3,4]。 要追加到的列表不为空,因此我们可以跳过该规则。 根据第二条规则,结果3作为第一个元素,后跟将[-10,-5,6,7,8]追加到[4]的结果。

因此,我们希望将[-10,-5,6,7,8]附加到 [4] . 要追加到的列表不为空,因此我们可以跳过该规则。 根据第二条规则,结果9作为第一个元素,后跟将[-10,-5,6,7,8]追加到[]的结果。

因此,我们希望将[-10,-5,6,7,8]附加到 [] . 要追加到的列表为空,因此根据第一条规则,结果为 [-10,-5,6,7,8]

由于将[-10,-5,6,7,8]追加到[]的结果是[-10,-5,6,7,8],因此将[-10,-5,6,7,8]追加到[4]的结果是[4,-10,-5,6,7,8]

由于将[-10,-5,6,7,8]追加到[4]的结果是[4,-10,-5,6,7,8],因此将[-10,-5,6,7,8]追加到[3,4]的结果是[3,4,-10,-5,6,7,8]

由于将[-10,-5,6,7,8]追加到[3,4]的结果是[3,4,-10,-5,6,7,8]的,因此将[-10,-5,6,7,8]追加到[2,3,4]的结果是[2,3,4,-10,-5,6,7,8]

由于将[-10,-5,6,7,8]追加到[2,3,4]的结果是[2,3,4,-10,-5,6,7,8],因此将[-10,-5,6,7,8]追加到[9,2,3,4]的结果是[9,2,3,4,-10,-5,6,7,8]

最新更新