斐波纳契函数中的递归堆栈溢出

时间:2014-09-20 10:56:16

标签: python recursion stack stack-overflow fibonacci

我正在试图理解递归函数的堆栈溢出机制。 所以我使用了这个斐波那契函数:

def fib(n):
 if n==1 or n==2:
    return 1
 return fib(n-1)+fib(n-2)
print (fib(555))

当我尝试使用此函数来计算fibo时(999)我得到了这个RuntimeError:相比之下超出了最大递归深度 但是当我尝试计算fibo(555)时,python不会打印任何运行时错误但仍可正常工作

我知道python中的默认递归deeptHs是1000但我不明白为什么python在我试图找到fibo时会打印运行时错误(555)

THK' X FOR ALL

1 个答案:

答案 0 :(得分:3)

可能是限制在堆栈深度而不是递归调用的数量,并且您可能在第一次调用之前用尽了一些堆栈深度到fib()

使用fib(555),您只能添加 555堆栈帧,而不是555 + 554。那是因为计算的两个项是按顺序完成的。换句话说,调用fib(555)并使用555个堆栈帧来完成它的工作,然后,这很重要,展开这些框架,以便在调用fib(555)之前回到处的堆栈级别。 然后调用 fib(554)它使用大约相同数量的帧。

在任何阶段你使用的不仅仅是额外的555堆栈帧。所以,从图形上看,正在做:

_                                      _
 \                                    /
  \           (555 levels)           /
   \__                            __/
      \                          /
       \  (another 554 levels)  /
        \______________________/

做的是:

_       _     _
 \     / \   /  (555 levels down, then
  \   /   \_/    back up, then down
   \_/           554, then back up again)

在任何情况下,使用递归来计算斐波纳契数是非常低效的,因为对于999,你计算fib(998) 两次,一个作为第一项的一部分{{ 1}}(fib(999)完成一个堆栈级别),一个作为第二个术语998。然后,对于这两个fib(998)次调用中的每个,您计算fib(998)两次。这是一种非常昂贵的时间方式,运行时间上升了(这个术语可能是错误的,那些具有更多数学性能的人可以纠正我,但我的意思是它随着数字的平方而上升)。

使用迭代解决方案要好得多,例如下面的伪代码(毫无疑问,它看起来很像Python,因为Python是一种理想的伪代码语言):

fib(997)

这比递归解决方案更有效,并且没有堆栈溢出问题。它几乎立即返回# Calculate Fibonacci, first term fib(0). def fib(n): if n <= 1: return 1 grandparent = 1 parent = 1 for i in range(n - 1): me = parent + grandparent grandparent = parent parent = me return me for i in range(10): print i, fib(i)

fib(999)

而不是整整十分钟我等待递归解决方案,然后我感到无聊和徘徊。