Prolog计算二叉树中的所有叶节点

Prolog计算二叉树中的所有叶节点,prolog,binary-tree,Prolog,Binary Tree,我需要使用prolog计算二叉树的所有内部节点,我可以使用以下代码计算所有节点 internal(tree(_,L,R), I) :- internal(L, I2), internal(R, I3), I is I2 + I3 + 1. internal(nil, 0). 我想把基本情况改成 internal(tree(_,nil, nil), 0). 我可以让它工作,但它返回错误 这里是一个测试用例,它应该返回4个内部(树(8,树(5,树(2,nil,nil),树(7,nil,nil))

我需要使用prolog计算二叉树的所有内部节点,我可以使用以下代码计算所有节点

internal(tree(_,L,R), I) :- internal(L, I2), internal(R, I3), I is I2 + I3 + 1.
internal(nil, 0).
我想把基本情况改成

internal(tree(_,nil, nil), 0).
我可以让它工作,但它返回错误

这里是一个测试用例,它应该返回4个内部(树(8,树(5,树(2,nil,nil),树(7,nil,nil)),树(9,nil,树(15,树(11,nil,nil),nil))),I)

谁能告诉我我的错误在哪里? 谢谢

读了你的建议后,我明白了,但还是失败了

internal(tree(_,L,R), I) :- internal(L, I2), internal(R, I3), I is I2 + I3. 
internal(tree(_,nil, R), I):- !, internal(R, I3), I is I3 + 1. 
internal(tree(_,L, nil), I):- !, internal(L, I3), I is I3 + 1.
internal(tree(_,nil, nil), 0).
internal(nil, 0).

如果将谓词更改为:

internal(tree(_,nil, nil), 0).
internal(tree(_,L,R), I) :- internal(L, I2), internal(R, I3), I is I2 + I3 + 1.
然后,对于具有
nil
子级和非
nil
子级的树,这将失败

确实:如果树是
tree(1,nil,tree(2,nil,nil))
,那么Prolog将首先尝试满足基本情况,但是sine
nil
不等于
树(u,nil,nil)
,失败。接下来,它旨在满足递归情况,并首先统一
L=nil
,和
R=tree(2,nil,nil)
。现在它调用
internal(L,I2)
,但由于
internal(nil,I1)
不能满足要求,因此失败

因此,我们可以首先构造一个谓词,如果两个子树产生一个内部节点,则该谓词满足:

isinternal(tree(_, _, _), _).
isinternal(_, tree(_, _, _)).
因此,如果至少有一个子树是
树(u,u,u)。
,则该谓词成功。现在,我们可以使用该谓词计算内部节点的数量:

internal(nil, 0).
internal(tree(_, nil, nil), 0).
internal(tree(_, L, R), I) :-
    isinternal(L, R),
    internal(L, NL),
    internal(R, NR),
    I is NL + NR + 1.

上述内容在可读性方面可以改进。我把这个留作练习。

提示:
+1
在这里做什么?您的呼叫结果是否使用了
l
l
不是一个变量,而是一个构造函数。因此您应该使用大写v标识符。@WillemVanOnsem因此调用使用大写i,而不是l,据我所知,在找到基本情况的解决方案后,+1将向每个节点添加1,该解决方案将返回0,但这里有一个
树(,nil,tree(,,,))
在您的示例中。如果您删除了
内部(nil,0)
,这与归纳或基本情况如何匹配?但是如果您有一个
树(u,nil,tree(u,,,,))
,那么左边的子项是
nil
,右边的子项是
,因此基本情况是不够的,归纳也不是令人满意的,由于它将在子级中调用
internal/2
,因此它将调用
internal(nil,I1)