递归调用的流程

时间:2013-08-06 03:38:52

标签: python python-2.7 recursion

我寻找这个问题的答案,但大多数是用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的新值? 谢谢。

1 个答案:

答案 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}}

,这些都不会使堆栈耗尽