Prolog 二叉树T的叶节点中的值列表

Prolog 二叉树T的叶节点中的值列表,prolog,binary-tree,dcg,Prolog,Binary Tree,Dcg,List是二叉树的叶节点中的值列表,我正试图找出如何输出它。这是给我所有的节点,但我只需要叶子 lea(nil,[]). lea(t(X,L,R),[X|L]) :- lea(L,L1), lea(R,L2), append(L1,L2,L). 运行此命令可以让我: ?- lea(t(a,t(b,t(d,nil,nil),t(e,nil,nil)),t(c,nil,t(f,t(g,nil,nil),nil))), List). List = [a, b,

List是二叉树的叶节点中的值列表,我正试图找出如何输出它。这是给我所有的节点,但我只需要叶子

lea(nil,[]).
lea(t(X,L,R),[X|L]) :-
   lea(L,L1), 
   lea(R,L2), 
   append(L1,L2,L).
运行此命令可以让我:

?- lea(t(a,t(b,t(d,nil,nil),t(e,nil,nil)),t(c,nil,t(f,t(g,nil,nil),nil))),
       List). 
List = [a, b, d, e, c, f, g]
但我需要

List = [d, e,g] 

有可能吗。

让我们使用DCG-确定子句语法。我们从您最初的定义开始:

lea(T, L) :-
   phrase(values(T), L).

values(nil) -->
   [].
values(t(X,L,R)) -->
   [X],
   values(L),
   values(R).
现在,我们需要把自己限制在那些属于树叶的
t/3
。一种可能性是列举所有案例:

lea2(T, L) :-
   phrase(leaves(T), L).

leaves(nil) -->
   [].
leaves(t(X,nil,nil)) -->
   [X].
leaves(t(_,L,R)) -->
   { dif(L+R,nil+nil) },
   leaves(L),
   leaves(R).
使用类似于的条件构造会更好、更有效。我想把这个留给感兴趣的人。

首先,我们扩展到与DCG的合作:

if_(C_1, Then_0, Else_0) -->                    % if_//3
   { call(C_1, Truth) },
   { functor(Truth, _, 0) },                    % safety check
   (  { Truth == true  } -> phrase(Then_0)
   ;  { Truth == false },   phrase(Else_0)
   ).
使用
if//3
,我们可以用一个子句(而不是两个子句)处理非nil树节点:


同一解决方案(距离首次实施不远)可以表示为:

lea(nil, []).
lea(t(X, nil, nil), [X]).
lea(t(_, A, B), L) :-
    lea(A, L1),
    lea(B, L2),
    append(L1, L2, L)
    L \= [].
最后一行(
L\=[]
)可以删除(如果您接受找到每个解决方案的可能性)。

不确定,但我认为(至少)在SWI Prolog中,您可以使用(->)/2构造directlyNo
(>)/2
立即提交,可能会删除部分解决方案集。是否应
调用(然后0)
阅读
短语(然后0)
?这样您就不再需要
添加//1
清空//0
。而且
(=)/3
相等真理/3
更紧凑。因此
如果(L-R=nil-nil[X],])
lea(nil, []).
lea(t(X, nil, nil), [X]).
lea(t(_, A, B), L) :-
    lea(A, L1),
    lea(B, L2),
    append(L1, L2, L)
    L \= [].