我正在试图理解递归函数的堆栈溢出机制。 所以我使用了这个斐波那契函数:
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
答案 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)
而不是整整十分钟我等待递归解决方案,然后我感到无聊和徘徊。