尾部递归是正常的一种特殊情况递归其中环境或堆栈框架与例程的每个实例相关联的函数可以通过例程末尾的递归调用重新使用(因为这是父例程要做的最后一件事)。首先,非尾递归(inC类):
int阶乘(int n){如果(n<=1)返回1;返回n*阶乘(n-1);}
注意,阶乘例程需要“记住”n的值,以便在递归调用返回时可以乘以它。
现在,一个真正的尾部递归版本:
int factorial_tail(int n,int累加器){如果(n<=1)回流蓄能器;返回factorial_tail(n-1,累加器*n);}int阶乘(int n){返回factorial_tail(n,1);}
注意,factorial_tail在执行递归调用时已经完成了所有相关的计算,因此它可以丢弃自己的n和accumulator值。
这让我们找到了关键转型这表明尾部递归相当于一个标准虽然()环:
int factorial_goto(int n,int累加器){开始时间:如果(n<=1)回流蓄能器;累加器*=n;n-=1;转到开始;}
一个人应该说服自己factorial_tail和factorial_goto在行为上是相同的;从那里,可以很容易地转换转到到while循环:
int factorial_while(int n,int累加器){而(n>1){累加器*=n;n-=1;}回流蓄能器;}
这是迭代和递归在中进行了讨论计算机科学类。一致性实施方案的方言LISP公司必须根据此转换实现尾部递归。尾部递归是一种更一般的转换的特例,称为尾箱优化; 基本上,任何C类以模式结尾的函数返回foo(args);可以转换为转到而不是引入额外的堆栈框架。