Tree 如何在prolog中计算树的叶子?

Tree 如何在prolog中计算树的叶子?,tree,prolog,Tree,Prolog,我试图计算一棵树的叶子数,但似乎做得不正确。任何帮助都将不胜感激。我尝试过几种不同的方法,但没有一种是正确的 nleaves(nil,0). nleaves(node(_,Left,Right),N):- nleaves(Left,N1),nleaves(Right,N2), N is N1+N2. 当我问这个问题时: ?-nleaves(3,节点(1,节点(2,节点(3,nil,nil),节点(4,nil,nil)),节点(5,nil,

我试图计算一棵树的叶子数,但似乎做得不正确。任何帮助都将不胜感激。我尝试过几种不同的方法,但没有一种是正确的

nleaves(nil,0).
nleaves(node(_,Left,Right),N):- nleaves(Left,N1),nleaves(Right,N2),
                            N is N1+N2.
当我问这个问题时: ?-nleaves(3,节点(1,节点(2,节点(3,nil,nil),节点(4,nil,nil)),节点(5,nil,nil)),N)。 它带着 N=0 现在,如果我在基本情况下将0设为1,并询问它返回的相同查询 N=6 那么如果我完全操纵谓词,它是完全错误的,是不可接受的

% nleaves(nil,0).
% nleaves(node(_, Left, Right),N):- nleaves(Left,LN), nleaves(Right,RN),
%                                              N is 3-LN+RN.
然后它会吐出来 N=3

我该怎么做才能让它以正确的方式表示N=3?我数不清树叶的数目。我似乎能够用max谓词帮助器正确计算高度

height(nil,0). % base case empty tree height is 0.
height(node(_,Left,Right),N):- height(Left,LN), height(Right,RN),
                           N is max(LN,RN)+1.

但是我不知道如何计算叶子。

所以叶子是指向2个零的节点,对吗

nleaves(nil,0).
nleaves(node(_,nil,nil),1).
nleaves(node(_,Left,Right),N):- 
    dif((Left,Right), (nil,nil)),
    nleaves(Left,N1),
    nleaves(Right,N2),
    N is N1+N2.

对于叶,基谓词应该是1,对于
nil
,基谓词应该是
0
,因此:

nleaves(nil, 0).
nleaves(node(_, nil, nil), 1).
nleaves(node(_, Left, Right), N) :-
    (dif(Left, nil); dif(Right, nil)),
    nleaves(Left, L),
    nleaves(Right, R),
    N is L + R.

在这里,第二个子句因此将一个叶
节点(u,nil,nil)
计算为一个,并且将两个项中至少一个不是
nil
的节点计算为两个节点的叶的总和;更普通的定义的类型如下所示:

leaf(Value)
node(Left, Right)
然后您可以像这样遍历它(我使用的是DCG表示法——如果您不了解发生了什么,请执行查询
listing(preorder)
,以查看代码扩展):

如果您想知道有多少叶子,只需在
值上使用
长度/2
谓词即可。或者,您可以修改累加器以执行以下运算:

count_leaves(Tree, Count) :-
    count_leaves(Tree, 0, Count).

count_leaves(leaf(_), Count0, Count) :-
    Count is Count0 + 1.
count_leaves(node(Left, Right), Count0, Count) :-
    count_leaves(Left, Count0, Count1),
    count_leaves(Right, Count1, Count).

对于第一个节点,它返回
0
,这一事实并不奇怪,因为
nil
你说
0
,而对于一个节点,你把这两个加起来,所以最终你只把零加起来,这等于零。为什么当我把0改成1时,它会吐出6?对不起,prolog是个新手,我真的很想知道如何数树叶。我也尝试过其他方法,可以吐出15个树的大小,但似乎不能把我的头绕在树叶的计数上。因为对于
nleaves(3,node(1,node(2,node(3,nil,nil),node(4,nil,nil)),node(5,nil,nil)),N)。
有六个
nil
s。这对
节点(2,nil,node(3,nil,nil))不起作用
。你是对的,我添加了nil casty,这有助于我了解N=6的情况。如何实现这个目标@Zasha:你可以通过点击答案左边的upvote/downvote按钮下面的灰色复选标记来接受Willem的答案。
?- test(V).
V = [1, 2, 3, 4].
count_leaves(Tree, Count) :-
    count_leaves(Tree, 0, Count).

count_leaves(leaf(_), Count0, Count) :-
    Count is Count0 + 1.
count_leaves(node(Left, Right), Count0, Count) :-
    count_leaves(Left, Count0, Count1),
    count_leaves(Right, Count1, Count).