[英]Confused about recursive counters in Prolog
几天来我一直被这个问题困扰。 所以给定一个形式为 t(Tree, Value, Tree) 的平衡树,我想找到左边树的深度,我用下面的代码做了:
depthLeft(nil, 1).
depthLeft(t(Tree1, _, _), N) :-
depthLeft(Tree1, N1),
N is N1 + 1.
所以代码有效,但我在柜台很困惑。 首先,为什么不能将计数器放在递归调用之上? 其次,为什么你不能争辩说 N1 是 N - 1 而不是像这里那样返回列表的第 n 个元素:
element_at(X,[X|_],1).
element_at(X,[_|L],K) :- K > 1, K1 is K - 1, element_at(X,L,K1).
我不明白为什么计数器在这里有不同的逻辑。 如果有人能指出我的方向,将不胜感激。
首先,为什么不能将计数器放在递归调用之上?
因为这样做是行不通的; Prolog 不是魔法,它以一种在真实计算机上运行的方式运行,这种方式对于 1970 年代的计算机来说足够简单 - 从顶部逐行:
depthLeft(t(Tree1, _, _), N) :- % this holds if
N is N1 + 1. % (calculate N1 + 1, error, N1 has no value).
depthLeft(Tree1, N1), % stopped before getting here.
其次,为什么你不能争辩说 N1 是 N - 1 而不是像这里那样返回列表的第 n 个元素:
反之,您提供K
作为所需元素的索引,以便在到达该代码后立即计算K-1
。 如果你想输入“我的树的深度是 4 吗?” 然后你可以重新排列,这样N1
就可以有一个值,但这与“我的树的深度是多少?”是不同的问题。
您可以从零开始计数,随着您下降到树中而增加,在末尾停止,以尾递归方式(没有剩余工作),然后返回最终计数。 或者你一无所知地下降到树中,等待稍后的加法工作,直到你到达末尾,在那里计数 1,然后通过调用堆栈上升回来做所有未决的加法,直到你回到你的答案开始。 这种方式往往写起来更简单但是吃的更多 memory 性能更差。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.