我寻找这个问题的答案,但大多数是用Python以外的编程语言给出的。
现在在这段代码中:
def f(n):
if n==0:
return 1
else:
m = f(n-1)
s = n * m
return s
我知道如果我使用例如n = 3,该函数将使用第二个分支来计算“3-1 = 2”然后将移动到同样的“2-1 = 1”到最后为0然后返回结果。
现在在下列情况下会发生什么:
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
假设我们用n = 5执行它。然后第三个分支用于返回fib(4)+ fib(3)。那么呢?程序使用哪个数字作为n,4或3的新值?
谢谢。
答案 0 :(得分:9)
作为参数给出5
的递归级别将自己调用两次,调用4
一次,使用3
调整一次,结果为4
两个电话将被加在一起。
同样,使用3
调用它会产生两个调用,一个调用2
,另一个调用 _____5_____
/ \
__4__ 3
/ \ / \
3 2 2 1
/ \ / \ / \
2 1 1 0 1 0
/ \
1 0
。等等。因此递归“树”将是:
5
\
4
\
3
\
2
\
1
你的更像“经典”的递归就像factorial一样,每个级别只调用一次,但这并不是递归的必要条件:
def fibonacci(x, n):
for i in range(x):
print " ",
print "Level %d called with %d"%(x,n)
if n == 0:
return 0
if n == 1:
return 1
return fibonacci(x+1,n-1) + fibonacci(x+1,n-2)
print fibonacci (0,5)
如果您想查看正在发生的事情,请将其更改为以下内容:
Level 0 called with 5
Level 1 called with 4
Level 2 called with 3
Level 3 called with 2
Level 4 called with 1
Level 4 called with 0
Level 3 called with 1
Level 2 called with 2
Level 3 called with 1
Level 3 called with 0
Level 1 called with 3
Level 2 called with 2
Level 3 called with 1
Level 3 called with 0
Level 2 called with 1
5
生成的输出:
fib(2)
你会看到我也删除了一些人使用的完全不必要的其他回归范式。它很少需要,并且可以降低代码的可读性。
解释了这一点后,您还应该了解可以滥用递归的情况。虽然Fibonacci序列可以优雅地编码为递归解决方案,但它不会过于高效,因为它会重新计算每个子分支中的许多不同值(例如在给定示例中计算三次5
,并且很多如果你使用比fact(20)
更大的参数调用它,可以多次使用。
即使factorial对于递归也不是那么好,因为它会非常缓慢地减少“搜索空间”:def fact (n): # n = 1..whatever
result = n
for i in range (2,n):
result = result * n
def fib(n): # n = 1..whatever
me = 1
if n >1:
grandparent = 1
parent = 1;
for i in range(2, n):
me = parent + grandparent
grandparent = parent
parent = me
return me
实际上会在堆栈上大约二十,而堆栈通常是有限的资源。
最好的递归算法是那些可以快速缩小搜索空间的算法,例如二进制搜索,它会在每个递归级别上将其减半。
知道何时使用递归通常与知道如何重要。
您可以使用因子和斐波那契的迭代解决方案,如:
n
对于大量{{1}}
,这些都不会使堆栈耗尽