Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用尾部递归实现Tak函数_C++_C_Compiler Optimization_Tail Recursion - Fatal编程技术网

C++ 使用尾部递归实现Tak函数

C++ 使用尾部递归实现Tak函数,c++,c,compiler-optimization,tail-recursion,C++,C,Compiler Optimization,Tail Recursion,是否有可能实施以下措施: 以某种方式在C/C++中递归尾部,以便gcc/g++能够执行尾部递归优化? 我不确定嵌套递归函数调用是否会混淆编译器。C++中的 尾递归优化要求只有1个递归调用(基本上允许它转换成循环),递归调用是函数中的最后一个操作: 例如: unsigned int f( unsigned int a ) { if ( a == 0 ) { return a; } return f( a - 1 ); // tail recursion

是否有可能实施以下措施:

以某种方式在C/C++中递归尾部,以便gcc/g++能够执行尾部递归优化?

我不确定嵌套递归函数调用是否会混淆编译器。C++中的

尾递归优化要求只有1个递归调用(基本上允许它转换成循环),递归调用是函数中的最后一个操作:

例如:

unsigned int f( unsigned int a ) 
{
   if ( a == 0 ) 
   {
      return a;
   }
   return f( a - 1 );   // tail recursion
}
由于Tak函数在每次“迭代”中需要4个递归调用:

如您所见,最后一个调用是递归的,但它内部有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;
}
inttak(intx,inty,intz)
{
while(x>y)
{
int oldx=x,oldy=y;
x=tak(x-1,y,z);
y=tak(y-1,z,oldx);

如果(x直接从你的数学定义出发,我们可以将函数写成:

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

但是,您不能使用尾部重新融合,因为它不能转换为循环。因为有多个重新融合调用。

我不这么认为?因为它只会开始执行所有操作,并保持分支?编译器是否可以将直接实现转换为循环实现?@jh314什么是循环“直接实现”?语句
返回tak(tak(x-1,y,z),tak(y-1,z,x),tak(z-1,x,y));
可能吗?呃。它不太可能看到这一点并将其转换为循环版本。循环为您带来的唯一好处是少一些函数调用(意味着调用堆栈不会被淹没太多)。递归调用的数量不是重要的变量。有些函数的一个递归调用不能转换为循环,有些函数的许多递归调用都可以。重要的是调用的位置。谢谢@Jules。非常感谢!
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;
}