答案 0 :(得分:1)
C ++中的尾递归优化要求只有1个递归调用(基本上允许它转换为循环),递归调用是函数中的最后一个操作:
示例:
unsigned int f( unsigned int a )
{
if ( a == 0 )
{
return a;
}
return f( a - 1 ); // tail recursion
}
由于Tak函数每次“迭代”需要4次递归调用:
int tak(int x, int y, int z)
{
if (x >= y)
{
return z;
}
else
{
return tak(tak(x-1, y, z), tak(y-1, z, x), tak(z-1, x, y)); // this is why it cannot happen
}
}
正如您所看到的,最后一次调用是递归调用,但它内部有3个递归调用。这可以防止尾递归优化(并且没有逻辑方法将其转换为非递归循环 - 这是获得尾递归优化所必需的。)
可以实施的另一种方式是:
int tak(int x, int y, int z)
{
while (x > y)
{
int oldx = x, oldy = y;
x = tak(x - 1, y, z);
y = tak(y - 1, z, oldx);
if (x <= y)
break;
z = tak(z - 1, oldx, oldy);
}
return z;
}
这又表明即使是循环形式,它仍然是递归的,阻止了尾递归优化。
答案 1 :(得分:0)
直接从数学定义中,我们可以将函数编写为:
int tak(int x, int y, int z){
if(x>y)
return tak(tak(1-x,y,z), tak(y-1,z,x), tak(z-1,x,y));
else
return z;
}
然而,由于无法将其转换为循环,因此无法进行尾部回退。由于有多个后退呼叫。