当前位置: 首页 > 知识库问答 >
问题:

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

况嘉运
2023-03-14

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

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

代码编译并输出正确的结果

共有1个答案

颜修真
2023-03-14
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);
}

正确地说,这个函数是尾部递归的。

尾部递归函数是指所有路径结束(即,返回)的函数,要么是一个值(-1表示负,prev2表示1和0),要么是对函数的调用(它不需要直接自身;但如果它不直接或间接调用自身,则不会是尾部递归)。

斐波那契并不是展示尾递归的好例子,因为这里它混淆了尾递归的好处(相当于迭代循环)和避免冗余调用的优化(原始fibonacci函数在最后一种情况下调用自己两次)。

考虑阶乘函数:

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

调用阶乘(5)时,调用堆栈如下所示:

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

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

 类似资料:
  • 我很难理解尾部递归的概念,我想为类似斐波那契函数a(n-3)a(n-2)制作一个尾部递归版本,到目前为止,这是我提出的,但我不知道这是否是一个正确的方法,有人能帮我吗,任何帮助都将不胜感激 代码输出正确的结果 但是当我实现尾部递归时,我的方法是分而治之的,但它不起作用,输出是错误的

  • 问题内容: 我在大学为我的Programming II类编写的程序需要一些帮助。这个问题要求人们使用递归来计算斐波那契数列。必须将计算出的斐波那契数存储在一个数组中,以停止不必要的重复计算并减少计算时间。 我设法使程序在没有数组和存储的情况下运行,现在我试图实现该功能,但遇到了麻烦。我不确定如何组织它。我已经浏览了Google并浏览了一些书,但没有太多帮助我解决如何实施解决方案的方法。 上面是不正

  • 我一直在试图理解Scheme中的尾部递归,我很难理解在使用斐波那契尾部递归的go-to示例中发生了什么。。。 如果这是尾递归或迭代斐波那契的代码: 我基本上可以理解每一行上发生的事情,除了这里: 这一行到底发生了什么?我在任何地方都找不到解释。我是计划的新手,到目前为止语法非常混乱。 或者有人能解释每一行发生了什么吗?这是我的基本理解,但我不确定我是否正确: 谢谢

  • 问题内容: 请解释以下简单代码: 我对最后一行感到困惑,特别是因为例如,如果n = 5,则将调用fibonacci(4)+ fibonacci(3),依此类推,但我不理解该算法如何以此来计算索引5的值方法。请详细解释! 问题答案: 在斐波那契数列中,每一项都是前两项的总和。因此,你编写了一个递归算法。 所以, 现在你已经知道了。因此,你可以随后计算其他值。 现在, 从斐波那契数列中我们可以看到斐波

  • 我试图想出一个程序,从用户那里获取任何数字,并生成斐波那契码的第n个数字。当我完成工作时,它会显示下一个,而不是我需要的。例如,我正在寻找第11个#和它的生产233而不是144。这是我的代码:

  • 本文向大家介绍Java递归实现斐波那契数列,包括了Java递归实现斐波那契数列的使用技巧和注意事项,需要的朋友参考一下 程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所