我从下面的程序中解释的是它是尾递归的,因为在函数返回时,最后没有什么可求的。我对吗?
void fun(int x)
{
if(x > 0)
{
fun(--x);
printf("%d\t", x);
fun(--x);
}
}
答案 0 :(得分:2)
恕我直言,这不是尾巴递归。
关键的区别在于,在尾部递归中,我们先计算值然后进行递归,这意味着我们不需要保留递归堆栈。在非尾递归中,我们先进行递归,然后计算。因此,在最终计算之前,我们必须存储递归堆栈。
在您的情况下,在我们第一次递归结束之前,我们无法执行print
步骤,这使得我们必须将x
值存储在堆栈中。如果删除了第一个递归调用,则应该是尾递归。
更新:
根据https://en.wikipedia.org/wiki/Tail_call,尾部递归应指代调用。如果我们谈论函数调用点的尾递归,那么程序中的第一个调用应该是非尾递归调用,而第二个调用是尾递归调用。
但是对于整个程序,我认为它并不是一个整体tail recursion
。
答案 1 :(得分:2)
不。对fun()
的第一次递归调用必须保存x
的当前值,进行新的函数调用,将其传递给副本,然后在调用者的作用域中恢复执行。
这不算在别针头上的天使。尾递归允许进行一些非常重要的编译器优化,例如能够重用相同的堆栈框架并就地更新所有参数值。顶部的非尾部调用无法做到这一点。如果您想证明该功能需要多少堆栈空间的上限,就可以。
也确实是,最后的呼叫(只有该呼叫)是尾递归的。编译器可以对其执行尾递归优化。删除第一个调用,该函数显然是尾递归的。