【问题标题】:Understanding recursion with the Fibonacci Series使用斐波那契数列理解递归
【发布时间】:2018-03-02 04:26:29
【问题描述】:

我试图更好地理解递归以及 return 语句的工作原理。因此,我正在查看一段代码,用于识别与给定术语相关的斐波那契数 - 在本例中为 4。我很难理解 else 语句。

def f(n):
  if n == 0:
    return 0
  if n == 1:
    return 1
  else:
    return f(n-1) + f(n-2)

f(4)

我曾尝试使用 Visualize Python 检查每一步发生的情况,但当它遇到 else 语句时我会迷路。

看起来它正在取 n 的值并减去 1,以创建一个新的 n 值 3,并将其返回给函数定义。所以它似乎只从 else 语句中的第一个函数返回值。但是,else 语句被编写为返回 2 个函数 f(n-1) + f(n-2) 的总和,在这种情况下,我认为返回值会是 5?你能把两个函数加在一起吗?

提前感谢您的帮助。

这里是Visualize Python Sum of 2 functions中代码的链接

【问题讨论】:

  • 这不是添加两个函数,而是将两个函数调用返回的整数相加。每个调用都是完全独立的,特别是每个调用都有自己的 n 私有值。

标签: python function recursion fibonacci


【解决方案1】:

如有疑问,请分解。

树形流与实际的控制流其实是反直觉的,但是一旦理解了调用的顺序,就会变得更加清晰。这里要理解的是,您不断将较大的计算分解为较小计算的总和,并且在遇到基本情况(if 语句)时停止。现在你可以进行所有的小计算,并将这些小计算的结果组合起来形成一个更大的结果,直到你得到最终的答案。

每次递归调用遇到基本情况时,它都会返回 1 或 0,具体取决于遇到的情况。该值将返回给前一个调用者。要理解,请考虑:

f(1)<sub>3</sub> + f(0)<sub>3</sub>

注意这里的下标代表递归调用树的深度。电话是f(2)<sub>2</sub>。先计算f(1)<sub>3</sub>,然后将1返回给f(2)<sub>2</sub>。然后计算f(0)<sub>3</sub>,并将0 返回到f(2)<sub>2</sub>。两个返回值相加,结果为1

f(2)<sub>2</sub> 然后 返回 1 给调用 it 的人,在这种情况下恰好是 f(3)<sub>1</sub>f(3)<sub>1</sub> 调用了f(2)<sub>2</sub> + f(1)<sub>2</sub>,同时另一个f(1)<sub>2</sub> 也将1 返回到f(3)<sub>1</sub>,现在f(3)<sub>1</sub> 将其与f(2)<sub>2</sub> 的结果相加,形成2

f(3)<sub>1</sub> 现在将2 传递给它的调用者f(4)<sub>0</sub>,而后者恰好调用了f(3)<sub>1</sub> + f(2)<sub>1</sub> ... 这样就可以了。


查看此问题的另一种方法是从实际进行的第一个函数调用开始:f(4)<sub>0</sub>

f(4)<sub>0</sub> 计算 f(3)<sub>1</sub> + f(2)<sub>1</sub>。但是要计算f(3)<sub>1</sub>,它需要知道f(2)<sub>2</sub> + f(1)<sub>2</sub>,同样,要计算f(2)<sub>1</sub>,它需要知道f(1)<sub>2</sub> + f(0)<sub>2</sub>,等等。

【讨论】:

  • 这太棒了。谢谢你。我仍然对 else 语句中的“+”号感到困惑,它是一个运算符,但显然在 else 语句中不起作用。有人可以为此提供解释吗?另一方面,我使用的可视化工具没有显示这两个函数同时运行。它只显示第一个函数的结果。不知道为什么会这样,但这让我很困惑。
  • @efw 我知道你来自哪里。就像我提到的那样,递归树与实际调用堆栈有点违反直觉。它更像是 f(4)0 -> f(3)1 -> f(2)2 -> f(1)3 -> 1 -> f(0)3 -> 0 -> f(1)2 - > ... 等等。 python中从左到右的评估。在检查递归树时,我们逐层遍历。这不是它在执行期间的实际完成方式。
  • 我想我现在明白了。代码首先在 else 语句中通过递归过程构建 n 个值的“列表”。最终,n 个值满足返回整数值的两个条件之一,它们的总数在最后一步中求和。再次感谢您的帮助。
【解决方案2】:

添加一些打印语句也可以帮助澄清顺序:

def f(n):
    print("Number received:", n)
    if n == 0:
        return 0
    if n == 1:
        return 1
    else:
        print("---- First recursion ----")
        a = f(n-1)
        print("---- Second recursion ----")
        b = f(n-2)
        print(" a=:",a,"; b=",b,"; returning:", a+b)
        return a + b

print("Final f(4)=", f(4))

输出:

Number received: 4
---- First recursion ----
Number received: 3
---- First recursion ----
Number received: 2
---- First recursion ----
Number received: 1
---- Second recursion ----
Number received: 0
 a=: 1 ; b= 0 ; returning: 1
---- Second recursion ----
Number received: 1
 a=: 1 ; b= 1 ; returning: 2
---- Second recursion ----
Number received: 2
---- First recursion ----
Number received: 1
---- Second recursion ----
Number received: 0
 a=: 1 ; b= 0 ; returning: 1
 a=: 2 ; b= 1 ; returning: 3
Final f(4)= 3

【讨论】:

  • 此代码无法处理输入中的大量数字。您也应该考虑运行时。
  • @Akshay Sapra 我同意避免记忆会使函数不灵活,但 OP 询问“返回语句如何工作”。掌握递归的基本原理在这里得到了很好的解决,这是手头的问题。
猜你喜欢
  • 2017-02-22
  • 2011-07-27
  • 2014-01-16
  • 2012-11-19
  • 2016-11-07
  • 2012-02-16
  • 1970-01-01
  • 2021-02-17
相关资源
最近更新 更多