第五章 python的函数(7):函数的递归(recursion)

什么是递归?

递归:在函数的执行过程中调用自己

5.6.1 递归的基本

  • 递归的特点:
    • 必须有明确的结束条件(否则会进入无限循环)
    • 每次进入更深一层递归时,问题规模比上次递归都应有所减少(朝结束条件更近一步)
    • 递归执行效率不高,浪费资源。所以能用迭代最好用迭代。
    • 递归层数过多会导致栈(stack)溢出(python的递归默认1000层,这个值可修改:sys模块的getrecursionlimit())

      在计算机中函数是通过栈(stack:先进后出)这种数据结果实现的。 每当一个函数调用,栈就会加一层栈帧(压栈),每当该函数返回,栈就减一层栈帧。(外层的函数会压在内层的下面) 由于栈的大小不是无限的,所以递归的层数过多会导致栈溢出。

    TODO:什么是栈内存?

  • 使用递归场景:堆排,快排,汉诺塔问题。(以后的知识点...)

  • 递归例:
def calc(n):  # 用递归取比n小的所有偶数
    print('递归:', n)
    n = int(n/2)
    if n > 0:
        calc(n)  # 函数内调用自身来递归。会一层一层往里执行
    print('出递归:', n)  # 调用函数后面的语句会从最里层函数开始往外执行。因为直到最里层才会走到这行。
    
calc(100)

执行结果:

递归: 100
递归: 50
递归: 25
递归: 12
递归: 6
递归: 3
递归: 1
出递归: 0
出递归: 1
出递归: 3
出递归: 6
出递归: 12
出递归: 25
出递归: 50
  • 扩展:栈是什么?

在计算机中,函数的调用时通过栈这种数据结构来实现的。(封装在解释器里)

那么什么是栈呢? 栈是一种先进后出的数据结构。 放在递归里来说,外层函数会最先压到栈(先进),然后依次压入其内部函数。
执行的时候,从最内层的函数开始一层一层往外执行,最外层会最后执行(后出)

5.6.2 递归的作用

  • 斐波那契数列
  • 汉诺塔
  • 多级评论数
  • 二分查找
  • 求阶乘( n! = 1234...n ):思路:n! = n * (n-1)!

5.6.3 扩展:尾递归优化(递归效率的优化)(c,js有尾递归)

注意:python解释器并没有尾递归的功能,所以这里的内容跟python无关。只是一个知识的扩展。

调用下一次递归的时候,用return 只调用的函数本身

递归效率低的原因:压栈的时候,由于调用内部函数之后还有处理,所以会保留栈帧。这样会消耗资源,所以效率低。

优化:当return的只有函数结果本身,那么程序不需要保存所有的递归函数代码块,而是只要保留返回值即可。效果接近for循环。

尾递归例:

def cal(n):
    print(n)
    return cal(n+1)  # 尾递归:直接返回下一层的函数结果,这里不能有运算。

cal(1)

非尾递归

def cal(n):
    print(n)
    return 1 + cal(n+1)  # 由于这里还有个 '1 +'的运算在等待下一层的返回值,所以这不是尾递归。

cal(1)

猜你喜欢

转载自www.cnblogs.com/py-xiaoqiang/p/11076843.html