Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 递归调用的流程_Python_Python 2.7_Recursion - Fatal编程技术网

Python 递归调用的流程

Python 递归调用的流程,python,python-2.7,recursion,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,然后

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

作为参数给定的递归级别将调用自身两次,一次调用
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
如果要查看发生了什么,请将其更改为以下内容:

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)
计算了三次,如果使用比
5
更大的参数调用它,则计算次数要多得多)

即使是阶乘也不太适合递归,因为它会缓慢地减少“搜索空间”:
fact(20)
实际上会在堆栈上深入二十层,而堆栈通常是有限的资源

最好的递归算法是那些能够快速减少搜索空间的算法,例如二进制搜索,它在每个递归级别上将搜索空间减半

知道何时使用递归通常比知道如何使用递归同样重要

您可以使用阶乘和斐波那契的迭代解决方案,如下所示:

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

而耗尽堆栈。在生成斐波那契数方面,您最好不要使用递归。非常感谢。我希望我能投票赞成你的答案。唉,我需要15个代表点才能做到这一点。@Quester,作为问题的提问者,你应该接受(使用绿色勾号)回答问题的最佳答案,并向那些有帮助的人投票(如果可以的话)。我很确定你总是可以接受的,尽管我已经有一段时间没有担任代表级别了:-)