计算Prolog上二叉树中的节点数量?

时间:2012-05-24 12:11:22

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

但目标总是回归号码为什么?

2 个答案:

答案 0 :(得分:5)

rbt_count_nodes(t(_,L,R),N)

应该成为

rbt_count_nodes(tree(_,L,R),N)

N=NL+NR+1

应该成为

N is NL + NR + 1

(=)/2用于执行统一,(is)/2用于执行算术。)

rbt_count_nodes(e,0):-!.

应该成为

rbt_count_nodes(nil,0).

在这三次编辑之后它应该没问题,但我无法测试,所以我可能被证明是错误的。

答案 1 :(得分:4)

除了另一个答案中给出的注释(使用is/2代替=/2以及术语t->树和e->名称中的拼写错误),您应该考虑使用一个累加器,允许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_count_nodes/2只调用rbt_count_nodes/3作为第二个参数(累加器)为零。在每个递归步骤时,此累加器增加1并进行递归。基本情况只是将累加器与输出结合在一起,允许系统进行尾递归并节省堆栈空间。

[编辑]

根据评论,要使其真正的尾递归(即所有递归调用都是尾调用),您可以向rbt_count_nodes / 3添加一个新子句(并修改另一个):

rbt_count_nodes(nil,N, N):-!.
rbt_count_nodes(tree(Node,tree(LNode, LL, LR),R),C,N):-
  rbt_count_nodes(tree(Node, LL, tree(LNode, LR, R)), C, N).
rbt_count_nodes(tree(_,nil,R),C,N):-
  succ(C, C1),
  rbt_count_nodes(R,C1, N).

使用这种方法,第一个子句处理一个空节点,第二个子句处理树的左侧,它只是将分支“移动”到当前节点的右侧,第三个子句只计算节点的数量。