我需要使用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).
答案 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 = nil
和R = 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.
在可读性方面可以改进上述内容。我将其保留为练习。