C 斐波那契函数的尾部递归版本

C 斐波那契函数的尾部递归版本,c,recursion,tail-recursion,C,Recursion,Tail Recursion,我很难理解尾部递归的概念, 我想做一个斐波那契函数的尾部递归版本,到目前为止,这就是我提出的 但我不知道它是否正确,有人能帮我吗,任何帮助都将不胜感激 #include <stdio.h> int fibonacci(int n) { if(n==1)return 1; if(n==2)return 1; return fibonacci(n-1)+fibonacci(n-2); } int fibonacci_tail_Recusive(int n,i

我很难理解尾部递归的概念, 我想做一个斐波那契函数的尾部递归版本,到目前为止,这就是我提出的 但我不知道它是否正确,有人能帮我吗,任何帮助都将不胜感激

#include <stdio.h>

int fibonacci(int n)
{
    if(n==1)return 1;
    if(n==2)return 1;
    return fibonacci(n-1)+fibonacci(n-2);
}


int fibonacci_tail_Recusive(int n,int prev1,int prev2)
{
    
    if(n<0) return -1;
    if(n==1||n==0) return prev2;
    return fibonacci_tail_Recusive(n-1,prev2+prev1,prev1);
}

int fibonacci_tail_Recusive_wrapper(int n)
{
    return fibonacci_tail_Recusive(n,1,1);
}


int main()
{
    printf("tail recursive result: %d  normal recursive result:%d", fibonacci_tail_Recusive_wrapper(23) ,fibonacci(23));

    return 0;
}
代码编译并输出正确的结果

int fibonacci_tail_Recusive(int n,int prev1,int prev2)
{
    
    if(n<0) return -1;
    if(n==1||n==0) return prev2;
    return fibonacci_tail_Recusive(n-1,prev2+prev1,prev1);
}
调用factorial5时,调用堆栈如下所示:

factorial(5)
   5 * factorial(4)
   5 * (4 * factorial(3))
   5 * (4 * (3 * factorial(2)))
   5 * (4 * (3 * (2 * factorial(1))))
   5 * (4 * (3 * (2 * 1)))
   5 * (4 * (3 * 2))
   5 * (4 * 6)
   5 * 24
   120
int factorial(int n, int acc)
{
    if (n == 0 || n == 1) return acc;
    return factorial(n - 1, acc * n);
}
factorial(5, 1);
factorial(4, 5);
factorial(3, 20);
factorial(2, 60);
factorial(1, 120);
120
在每一步中,乘法器都在等待下一个操作数,以便计算其结果,这意味着每一步都需要保留一定量的内存

使用尾部递归函数,如下所示:

factorial(5)
   5 * factorial(4)
   5 * (4 * factorial(3))
   5 * (4 * (3 * factorial(2)))
   5 * (4 * (3 * (2 * factorial(1))))
   5 * (4 * (3 * (2 * 1)))
   5 * (4 * (3 * 2))
   5 * (4 * 6)
   5 * 24
   120
int factorial(int n, int acc)
{
    if (n == 0 || n == 1) return acc;
    return factorial(n - 1, acc * n);
}
factorial(5, 1);
factorial(4, 5);
factorial(3, 20);
factorial(2, 60);
factorial(1, 120);
120
调用堆栈如下所示:

factorial(5)
   5 * factorial(4)
   5 * (4 * factorial(3))
   5 * (4 * (3 * factorial(2)))
   5 * (4 * (3 * (2 * factorial(1))))
   5 * (4 * (3 * (2 * 1)))
   5 * (4 * (3 * 2))
   5 * (4 * 6)
   5 * 24
   120
int factorial(int n, int acc)
{
    if (n == 0 || n == 1) return acc;
    return factorial(n - 1, acc * n);
}
factorial(5, 1);
factorial(4, 5);
factorial(3, 20);
factorial(2, 60);
factorial(1, 120);
120
因为在每一步函数都完成了它需要执行的所有计算,所以它不需要为结果保存任何内存;每次调用都覆盖当前帧;换句话说,它可以重写为一个循环:

int factorial(int n, int acc)
{
    while (true) {
        if (n == 0 || n == 1) return acc;
        acc = acc * n;
        n = n - 1;
    }
}

如果编译器足够聪明,尾部递归函数的代码将转换为该函数将生成的等效代码。

而且编译器没有抱怨斐波那契函数缺少返回语句?我觉得很难相信。始终将警告视为必须修复的错误。@Someprogrammerdude当警告在clang中默认启用时,gcc需要[minimally]-Wall[或just-Wreturn type]输出正确的结果并不能证明程序是正确的,特别是当它显然是错误的缺少返回时。如果您添加了返回,如果有帮助的话,那么尾部递归将是正确的!默认情况下,即使使用-Wall,clang仍会启用更多警告。gcc需要——Wextra也需要。给定:int x=3;int y=19;void foovid{如果x<5;y=7;}旧的gcc甚至通过了-Wall。最近gcc将对其进行标记