如何将以下内容转换为尾递归版本。
sum(void,0).
sum(t(V,L,R),S) :-
sum(L,S1),
sum(R,S2),
S is V + S1 + S2.
似乎不可能维持单个累加器,因为分支的幅度为2 ^ n。
一种可能的解决方案是让累加器在每次迭代时将新累加器添加到列表中。 也许上述解决方案是最优的?
提前致谢。
答案 0 :(得分:2)
是的,您的解决方案是最佳的,因为它将为树中的每个节点调用sum / 2谓词一次(并且您根本无法进行较少的调用)。不,你可以通过使用累加器自己实现堆栈来使其尾递归。
这是一个例子(未经测试)。扁平谓词可以与sum结合,但是为了清晰起见它们是不同的(两者都是尾递归):
flatten([], Acc, Acc).
flatten([void|ToGo], Acc, Result) :-
flatten(ToGo, Acc, Result).
flatten([t(V,L,R)|ToGo], Acc, Result) :-
flatten([L,R|ToGo], [t(V,L,R)|Acc], Result).
flatten(Root, Result) :-
flatten([Root], [], Result).
sum([], Result, Result).
sum([t(V,_,_)|ToGo], Acc, Result) :-
NewAcc is Acc+V,
sum(ToGo, NewAcc, Result).
sum(Tree, Result) :-
flatten(Tree, FlatTree),
sum(FlatTree, 0, Result).