我已经使用'is_a(X,Y)'在'prolog'中制作了一个'tree'。看起来像这样:
is_tree('b', 'a').
is_tree('c', 'a').
is_tree('d', 'b').
is_tree('e', 'b').
is_tree('f', 'c').
is_tree('g', 'c').
a
b c
d e f g
现在我正在尝试查找所有叶子节点,它们将是d, e, f, g
。
到目前为止,我已经成功地write()'ing
出了第一个叶子,但是我不知道如何回到树上查找其他节点,以及如何写closing clause
来查找值。< / p>
find_leaf(X, Y):-
\+is_tree(X, Y).
find_leaf(X, Y):-
is_tree(A, Y), !,
find_leaf(Y, A).
find_leaf(X, Y):-
is_tree(A, X),
write(Y),
find_leaf(Y, A).
如何才能“再次备份”以找到其他叶子?正确的“结束语”是什么?
答案 0 :(得分:1)
Prolog中大多数谓词都不write/1
。就像命令式编程和函数式编程一样,通常,大量函数会计算,然后其他函数会“通信”(通过写入控制台,更改用户界面等)。
因此,我建议构造一个谓词find_leaf(X)
,以将变量X
与叶子统一起来。由于Prolog的回溯机制,我们最终可以统一所有叶子。
is_tree/2
谓词中获取节点在这里,除非您没有提及,否则节点只能通过分析is_tree/2
谓词来获得,其中第一项是“子”,第二项是“父”。我们知道,如果这是一个节点而不是父节点,则该事为假。由于没有其他机制来定义树,因此节点(可能)是某些is_tree
谓词中的子级。
因此,我们可以实现一个谓词来查找具有以下内容的子项:
find_leave(X) :-
is_tree(X, _),
\+ is_tree(_, X).
因此,第一个调用is_tree(X, _)
将使X
与树中的一个子元素统一,而第二个调用将验证X
没有一个子元素。
然后产生:
?- find_leave(X).
X = d ;
X = e ;
X = f ;
X = g.
我们还可以通过参数传递根,例如:find_leave(b, X)
将X
与b
的所有子元素统一。我们在这里有两种情况:
R
(不是根)不是父母,在这种情况下,R = X
(R
是请假);和find_leave(C, X)
称为C
。由于回溯,最终我们将获得所有叶子。所以:
find_leave(R, R) :-
\+ is_tree(_, R).
find_leave(R, X) :-
is_tree(C, R),
find_leave(C, X).
因此,我们为不同的根获得了不同的叶子:
?- find_leave(a, X).
X = d ;
X = e ;
X = f ;
X = g ;
false.
?- find_leave(b, X).
X = d ;
X = e ;
false.
?- find_leave(R, X).
R = a,
X = d ;
R = a,
X = e ;
R = a,
X = f ;
R = a,
X = g ;
R = b,
X = d ;
R = b,
X = e ;
R = c,
X = f ;
R = c,
X = g ;
false.