Prolog对二叉树中的所有叶子节点进行计数

时间:2018-10-26 06:31:09

标签: 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).

我可以使它工作,但它返回false。

这是一个测试用例,应该返回4内部(tree(8,tree(5,tree(2,nil,nil),tree(7,nil,nil)),tree(9,nil,tree(15 ,tree(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).

1 个答案:

答案 0 :(得分:1)

如果将谓词更改为:

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首先将尝试满足基本情况,但是正弦nil不等于tree(_, nil, nil)时,将失败。接下来,它旨在满足递归情况,并首先统一L = nilR = tree(2, nil, nil)。现在调用internal(L, I2),但是由于无法满足internal(nil, I1),因此失败了。

因此,我们可以首先构造一个满足两个子树是否导致内部节点的谓词:

isinternal(tree(_, _, _), _).
isinternal(_, tree(_, _, _)).

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

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.

在可读性方面可以改进上述内容。我将其保留为练习。