使用尾递归实现Tak函数

时间:2013-11-13 19:31:34

标签: c++ c compiler-optimization tail-recursion

是否可以实施Tak function

enter image description here

以C / C ++的形式递归尾部,以便gcc / g ++可以执行尾递归优化?
我不确定嵌套的递归函数调用是否会混淆编译器。

2 个答案:

答案 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;
} 

然而,由于无法将其转换为循环,因此无法进行尾部回退。由于有多个后退呼叫。