在Prolog上计算二叉树中的节点数?
我有一些密码在Prolog上计算二叉树中的节点数?,prolog,binary-tree,Prolog,Binary Tree,我有一些密码 tree1(tree(1, tree(2, tree(3,nil,nil), tree(4,nil,nil)), tree(5, tree(6,nil,nil), tree(7,nil,nil)) ) ). rbt_count_nodes(e,0):-!. rbt_count_node
tree1(tree(1,
tree(2,
tree(3,nil,nil),
tree(4,nil,nil)),
tree(5,
tree(6,nil,nil),
tree(7,nil,nil))
)
).
rbt_count_nodes(e,0):-!.
rbt_count_nodes(t(_,L,R),N):-
rbt_count_nodes(L,NL),
rbt_count_nodes(R,NR),
N=NL+NR+1.
?-tree1(T),rbt_count_nodes(T,N),write(N).
但进球总是没有。为什么
rbt_count_nodes(t(_,L,R),N)
应该成为
rbt_count_nodes(tree(_,L,R),N)
N is NL + NR + 1
rbt_count_nodes(nil,0).
及
应该成为
rbt_count_nodes(tree(_,L,R),N)
N is NL + NR + 1
rbt_count_nodes(nil,0).
((=)/2
用于执行统一,(is)/2
用于执行算术)
及
应该成为
rbt_count_nodes(tree(_,L,R),N)
N is NL + NR + 1
rbt_count_nodes(nil,0).
在这三次编辑之后应该没问题,尽管我无法测试,因此可能会被证明是错的。在另一个答案中给出的注释旁边(使用
is/2
而不是=/2
以及术语t->tree和e->empty的名称中的打字错误),应该考虑使用累加器来允许Prolog系统执行尾部递归:
rbt_count_nodes(T,N):-
rbt_count_nodes(T, 0, N).
rbt_count_nodes(nil,N, N):-!.
rbt_count_nodes(tree(_,L,R),C,N):-
succ(C, C1),
rbt_count_nodes(L,C1,NL),
rbt_count_nodes(R,NL,N).
过程rbt\u count\u nodes/2
仅调用rbt\u count\u nodes/3
,第二个参数为零(累加器)。在每个递归步骤中,该累加器都会递增1并执行递归。基本情况只是将累加器与输出统一起来,允许系统执行尾部递归并节省堆栈空间
[编辑]
根据注释,要使其真正成为尾部递归(即所有递归调用都是尾部调用),您可以向rbt_count_nodes/3添加一个新子句(并修改另一个):
使用这种方法,第一个子句处理一个空节点,第二个子句处理树的左侧,它只是将分支“移动”到当前节点的右侧,第三个子句只计算节点数。对此,我只能补充一点,Prolog数据是符号的,Prolog统一是符号数据的结构统一;而
is
在假设参数表达式描述算术实体的情况下强制参数表达式。您可以随时在以下位置进行测试:)这段代码不是尾部递归的。您不需要剪切,因为nil
和树(,,,)
是互斥的选择。@Will Ness:这段代码是尾部递归的,为什么不这样说?。我刚刚修改了操作码,所以我留下了切口。@Mog:关于变量名,你说得对。改了那个名字!它不是尾部递归的,因为谓词在最后一条指令之前调用自己(即使最后一条指令也是对istelf的调用)。这意味着Prolog必须保存上下文,这与尾部递归方法不同。我认为它在技术上是尾部递归的,因为在最后一次递归调用时,它将丢弃上下文。但是,您是对的,对其本身的第一个递归调用确实需要retain上下文。