【问题标题】:How is the value returned? - recursive algorithm值如何返回? - 递归算法
【发布时间】:2017-05-16 17:53:04
【问题描述】:

我无法理解这个简单的递归算法是如何返回值的。算法如下:

int fib(int n)
{
     if (n <= 1)
         return n;

     return fib(n-1) + fib(n-2);

}

我想知道在这个函数中输入 5 是如何返回 5 的? 我知道第五个斐波那契数是 5,所以这是正确的答案,但我不确定这个答案是如何从上面的代码得出的.前五个斐波那契数:1 1 2 3 5。

根据我有限的理解,我认为将 5 传递给该函数会返回 7。这是因为 5-1 = 4 和 5 - 2 = 3。然后将这两个数字相加得到简单的整数 7。这有意义吗?我确信我已经失去了阅读这篇文章的人,尽管这很简单。如果我读到这篇文章,我会迷路的。

另外,如果我创建一个递归树并显示从 5 开始对 fib 的递归调用,我看不到它最终如何返回 5,但我确实看到了对函数 fib() 的所有调用,直到最终返回 1,因为fib() 的参数是 0 或 1。我绘制的递归树只是此 page 中所示的递归树的副本。

谁能帮我理解这个递归算法?

【问题讨论】:

  • 如果您想了解递归,我将从一个更简单的示例开始。递归阶乘函数可能更容易理解。
  • 它没有说return (n-1) + (n-2);。它说return fib(n-1) + fib(n-2);。换句话说,n == 5 是在做return fib(4) + fib(3);
  • @FrançoisAndrieux - 但是什么是 fib(4)fib(3),分解为递归调用? :-)
  • 你检查你的树节点的值了吗?总结一下:fib(1) + fib(0) + fib(1) + fib(1) + fib(0) + fib(1) + fib(0) + fib(1) 会变成= 5
  • 如果我把树上所有的加起来,那么它实际上等于 5!哇!感谢您的评论。很有帮助...

标签: c++ algorithm recursion


【解决方案1】:

好的,让我们打开fib(5)的递归

fib(5) = fib(4) + fib(3)
fib(4) = fib(3) + fib(2)
fib(3) = fib(2) + fib(1)
fib(2) = fib(1) + fib(0)
fib(1) = 1
fib(0) = 0

fib(1) + fib(0) = 1 + 0 = 1 so fib(2) = 1
fib(2) + fib(1) = 1 + 1 = 2 so fib(3) = 2
fib(3) + fib(2) = 2 + 1 = 3 so fib(4) = 3
fib(4) + fib(3) = 3 + 2 = 5 so fib(5) = 5

5-1 = 4 和 5-2 = 3 是对的,但这仅表示您正在调用 fib(4) + fib(3) = 5,这与 4 + 3 = 7 非常不同

【讨论】:

  • 感谢您对我的包容。我认为我现在明白了。 :) 你在工作中也编程 Go 真是太棒了。
【解决方案2】:

这是我的递归调用树版本:

fib(5) = fib(4)                                     + fib(3)

         |                                            |
         +--------------------------\                 +-----------------\
         |                          |                 |                 |

       = fib(3)                   + fib(2)          + fib(2)          + fib(1)

         |                          |                 |                 |
         +-----------------\        +--------\        +--------\        |
         |                 |        |        |        |        |        |

       = fib(2)          + fib(1) + fib(1) + fib(0) + fib(1) + fib(0) + 1

         |                 |        |        |        |        |        |
         +--------\        |        |        |        |        |        |
         |        |        |        |        |        |        |        |

       = fib(1) + fib(0) + 1      + 1      + 0      + 1      + 0      + 1

         |        |        |        |        |        |        |        |
         |        |        |        |        |        |        |        |
         |        |        |        |        |        |        |        |

       = 1      + 0      + 1      + 1      + 0      + 1      + 0      + 1

       = 5

【讨论】:

  • 太美了!
  • 是的,我同意@BoundaryImposition 这是很酷的 ASCII 艺术。 :) 这张图也很准确。
【解决方案3】:

将 return 视为返回一个数字,为​​了获得该数字,它必须调用一个函数并运行该函数。它会一直这样做,直到达到基本情况 n = 0 或 1,然后它不会调用另一个函数来返回一个数字。

【讨论】:

    【解决方案4】:

    当使用递归函数时,会维护一个隐式堆栈,用于跟踪从每个递归调用返回的值。

    现在让我们考虑给定 n=5 值的示例

    >Processing fib(5)... Call fib(3) and fib(4).
    >Processing fib(3)... Call fib(1) and fib(2).
    >Processing fib(1)... Return 1!
    >Processing fib(2)... Return 1!
    >Processing fib(4)... Call fib(2) and fib(3).
    >Processing fib(2)... Return 1!
    >Processing fib(3)... Call fib(1) and fib(2).
    >Processing fib(1)... Return 1!
    >Processing fib(2)... Return 1!
    >5 is the 5th Fibonacci number
    

    分析:程序要求在第 15 行找到一个数字并将该数字分配给目标。然后它用目标调用 fib()。执行分支到 fib() 函数,在第 28 行,它打印它的参数。

    在第 30 行测试参数 n 是等于 1 还是等于 2;如果是,则 fib() 返回。否则,它返回通过在 n-2 和 n-1 上调用 fib() 返回的值的总和。

    在示例中,n 为 5,因此从 main() 调用 fib(5)。执行跳转到 fib() 函数,并在第 30 行测试 n 是否小于 3。测试失败,因此 fib(5) 返回 fib(3) 和 fib(4) 返回的值的总和。也就是说,在 n-2 (5 - 2 = 3) 和 n-1 (5 - 1 = 4) 上调用 fib()。 fib(4) 将返回 3,fib(3) 将返回 2,因此最终答案将是 5。

    因为 fib(4) 传入的参数不小于 3,所以会再次调用 fib(),这次是 3 和 2。fib(3) 会依次调用 fib(2) 和 fib(1 )。最后,对 fib(2) 和 fib(1) 的调用都将返回 1,因为这些是停止条件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 1970-01-01
      相关资源
      最近更新 更多