对一个谓词进行编码,该谓词将在一个树中找到一个只有一个子节点的所有节点。 有了树
treeEx(X) :-
X = t(73,t(31,t(5,nil,nil),nil),t(101,t(83,nil,t(97,nil,nil)),nil)).
73
/ \
31 101
/ /
5 83
/
97
它应该返回L = [31, 101, 83]
我尝试了以下操作,但是它返回了所有节点。我不知道如何仅列出单个子节点。
single(nil,[]).
single(t(X,L,R),[X|S]) :-
append(SL,SR,S), single(L,SL), single(R,SR).
答案 0 :(得分:1)
[..]谓词,该谓词查找树中的所有节点与一个单个子节点。
首先考虑一下您感兴趣的情况:
usecols
:=具有值t(V,nil,R)
和单个(右)子节点V
的节点。R
:=具有值t(V,L,nil)
和单个(左侧)子元素V
的节点。然后考虑其他您不感兴趣的情况(尽可能笼统地说):
L
:=值为t(V,nil,nil)
且没有子节点的节点。V
:=值为t(V,L,R)
的节点,左节点({V
)和右节点(L
)都是接下来考虑您要“做什么”:收集列表中您感兴趣的案例的值。因此,如果您有感兴趣的案例,则需要将值R
添加到包含结果的列表中:
V
这样,您可以编写谓词:您知道它具有一个“输入”参数(树)和一个“输出”参数(列表)。首先是您感兴趣的情况:
[V|RestResults] % whatever RestResults is, not important atm
您将值single(t(V, nil, R), [V|Vr]) :- single(R, Vr).
single(t(V, L, nil), [V|Vl]) :- single(L, Vl).
添加到从单个子分支获得的结果(值列表)中。
接下来是您不感兴趣的案例。首先是简单的案例:
V
那是一个叶子节点(没有子节点)。它的值没什么意思,它的子代可能没有结果,所以结果列表是空列表。
最后,最复杂的情况:
single(t(_,nil,nil), []).
两个孩子;在这种情况下,该值并不有趣,但是子级是:您需要收集其结果列表,并将其追加以创建此节点的结果列表。
现在,您编写这些规则的顺序在Prolog中通常很重要,但是在这种情况下,顺序并不重要(当Prolog对节点使用“错误”规则时,例如最后一个-两个孩子-一个single(t(_, L, R), X) :- single(L, Vl), single(R, Vr), append(Vl, Vr, X).
,然后它很快就会到达t(_,nil,nil)
的情况下-没有规则匹配,并且回溯到“正确”规则)。尽管如此,我还是要根据规则的模式有多“具体”对规则进行排序:首先,该规则不包含任何孩子,然后两个规则对应一个孩子,最后一个规则对应两个孩子。
({Live on ideone)