普通递归
求和操作是在“归”的过程中执行的,每层返回后都要再执行一次求和操作。
/* 递归 */
int recur(int n) {
// 终止条件
if (n == 1)
return 1;
// 递:递归调用
int res = recur(n - 1);
// 归:返回结果
return n + res;
}
函数没有执行完成(没有返回值)的时候就自己调用了自己,直道到达终止条件,此时函数终于有了返回值,栈中的函数也会依次得到返回值从而被相继释放
尾递归
求和操作是在“递”的过程中执行的,“归”的过程只需层层返回。
/* 尾递归 */
int tailRecur(int n, int res) {
// 终止条件
if (n == 0)
return res;
// 尾递归调用
return tailRecur(n - 1, res + n);
}
问题
写成下面形式算尾递归吗?
int recur(int n) {
// 终止条件
if (n == 1)
return 1;
return n + recur(n - 1);
}
不是。
尾递归是指在函数返回的时候,仅执行递归调用而不需额外的操作。也就是说,在递归调用之后没有剩余的操作需要完成。这样的递归可以被优化,编译器或解释器可以在某些情况下重用现有的栈帧,而不是为每次递归调用创建新的栈帧,从而避免栈溢出的问题。
在这个例子中,虽然递归调用 recur(n - 1) 是在最后一行,但在递归调用返回后还需要执行 n + … 这个操作,所以它不是一个简单的尾递归。每次递归调用都需要保留一些信息以便在返回时进行加法运算,这会导致栈空间的使用随递归深度增加而线性增长。
如果要将此函数改写为尾递归的形式,我们可以使用一个辅助函数和累加器参数来传递中间结果
int tail_recur(int n, int accumulator = 0) {
if (n == 0)
return accumulator;
return tail_recur(n - 1, accumulator + n);
}