Возможно ли реализовать функцию Tak:
хвост рекурсивно в 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 рекурсивных вызова на "итерацию":
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;
}
Что еще раз показывает, что даже в форме цикла он все еще рекурсивно, предотвращая оптимизацию хвостовой рекурсии.
Исходя из вашего определения математики, мы можем просто написать функцию как:
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;
}
Однако вы не можете сделать это с помощью хвостика, поскольку он не может быть преобразован в цикл. Поскольку существует более одного призыва к рекрутингу.