• Python 基础之递归 递归函数 尾递归 斐波那契


    1.递归函数

    定义:自己调用自己的函数
    :
    :
    有去有回是递归
    #(1)简单的递归函数
    def digui(n):
        print(n)
        if n > 0:
            digui(n-1)
        print(n)

    digui(5)
    '''
    代码解析:
    去的过程:
    n = 5
    print(5) 5>0 digui(5-1) => digui(4) 执行到第12行,自己调用自己,代码暂定在12行,发生阻塞
    print(4) 4>0 digui(4-1) => digui(3) 执行到第12行,自己调用自己,代码暂定在12行,发生阻塞
    print(3) 3>0 digui(3-1) => digui(2) 执行到第12行,自己调用自己,代码暂定在12行,发生阻塞
    print(2) 2>0 digui(2-1) => digui(1) 执行到第12行,自己调用自己,代码暂定在12行,发生阻塞
    print(1) 1>0 digui(1-1) => digui(0) 执行到第12行,自己调用自己,代码暂定在12行,发生阻塞
    print(0) 0>0? 条件不满足,代码向下执行,
    print(0)
    如果函数执行到最后一行调用结束,要触底反弹,回到上一层函数调用处
    回的过程:
    print(1) 回到函数为1的第12 代码继续向下执行, print(1)
    print(2) 回到函数为1的第12 代码继续向下执行, print(2)
    print(3) 回到函数为1的第12 代码继续向下执行, print(3)
    print(4) 回到函数为1的第12 代码继续向下执行, print(4)
    print(5) 回到函数为1的第12 代码继续向下执行, print(5)
    5,4,3,2,1,0,0,1,2,3,4,5


    栈帧空间: 负责运行函数而开辟的空间
    (1)递归函数整体过程,调用一层函数就是开辟一层栈帧空间,结束一层函数,就是释放一层栈帧空间,
    递归函数实际上就是开辟和释放栈帧空间的过程
    (2)递归函数回的过程:如果函数走到最后一层执行结束了,要回到上一层空间函数调用处,继续向下执行,直到所有代码执行完毕,
    在触发触底反弹操作,回到上一层空间函数调用处,以此类推...
    直到所有的函数全都释放掉,那么这个递归函数彻底终止.
    (3)写递归函数的时候切记要加上一个终止的条件,否则会发生内存溢出,如果层数不多,不推荐使用递归

    递归函数通过两个条件触发回的过程:
    (1)当前函数彻底执行完毕的时候,触发回的过程,回到上一层函数的调用处
    (2)当前函数遇到return 返回值的时,触发回的过程,回到上一层函数的调用处
    #计算任意数n的阶乘
    #5! 5*4*3*2*1
    #8! 8*7*6*5*4*3*2*1
    #普通方法
    n = 5
    total = 1
    for i in range(1,n+1):
        total *= i
    print(total)

    #递归方法
    def jiecheng():
        if n <= 1:
            return 1
        return n * jiecheng(n-1)

    #jiecheng(1) =>1
    '''
    代码解析:
    去的过程:
    n = 5 return 5 * jiecheng(5-1) => 5 * jiecheng(4)
    n = 4 return 4 * jiecheng(4-1) => 4 * jiecheng(3)
    n = 3 return 3 * jiecheng(3-1) => 3 * jiecheng(2)
    n = 2 return 2 * jiecheng(2-1) => 2 * jiecheng(1)
    n = 1 return 1

    回的过程:
    n = 2 return 2 * jiecheng(2-1) => 2*1
    n = 3 return 3 * jiechneg(3-1) => 3*2*1
    n = 4 return 4 * jiecheng(4-1) => 4*3*2*1
    n = 5 return 5 * jiecheng(5-1) =>5*4*3*2*1

    res = 5 * 4 * 3 * 2 * 1 = 120

    2.尾递归

    #尾递归:只返回递归函数本身且非表达式(没有运算(+,-,*,/..))

    只开辟一个栈帧空间完成递归函数(因为最终的返回值就是第一层空间的返回值,所以只需要一层栈帧空间即可,不停的进行替换)
    cpython解释器不支持,可以换一个支持尾递归的解释器(比如在公司内部大型服务器架构的解释器 推荐使用)
    #方法一:
    def jiecheng2(n,endval=1):
        if n <= 1:
            return endval
        return jiecheng2(n-1,n*endval)
    res = jiecheng2(5,1)
    print(res)


    '''
    #去的过程
    n = 5 endval=1
        return jiecheng(5-1,5*1) => jiecheng(4,5*1)
    n = 4 endval = 5 * 1
        return jiecheng(4-1,4* 5*1) =>jiecheng(3,4*5*1)
     n=3 endval = 4*5*1
       return jiecheng(3-1,3* 4*5*1) => jiecheng(2, 3*4*5*1)
    n=2 endval = 3*4*5*1
       return jiecheng(2-1,2* 3*4*5*1) => jiecheng(1, 2*3*4*5*1)
    n=1 endval = 2*3*4*5*1
       n < = 1 这个条件满足了,直接返回endval


    #回的过程
    n = 2 endval = 3*4*5*1
        return jiecheng(2-1,2* 3*4*5*1) => 2*3*4*5*1
    n = 3 endval = 4*5*1
        return jiecheng(3-1,3* 4*5*1)   => 2*3*4*5*1
    n = 4 endval = 5*1
        return jiecheng(4-1,4 *5*1) => 2*3*4*5*1
    n = 5 endval = 1
         return jiecheng(5-1,5*1) => 2*3*4*5*1   

    如果运行到最后一层函数,有返回值了,那么这个返回值就是最终的值,
    所有尾递归只需要一层栈帧空间
    '''
    #方法二 优化版
    #系统底层用
    def jiecehng2(n,endval):
        if n<=1:
            return endval
        return jiecehng2(n-1,n*endval)
    #给用户用 不需要用户填写第二个参数(比较人性化)
    def jiecheng3(n):
        return jiecehng2(n,1)
    res = jiecheng3(5)
    print(res)

    3.斐波那契序列

    # 1 1 2 3 5 8 13 21 34 55
    #第n个数 它的数值是多少?
    #除了前2个,后面每一个值都是上一个数 + 上上的数两者之和
    def fib(n):
        if n == 1 or n == 2:
            return 1

        return fib(n-1) + fib(n-2)
    res = fib(45)
    print(res)

    '''
    代码解析:
    n = 5
    => return fib(5-1) + fib(5-2)
    => return fib(4)  + fib(3) => 3 + 2 => 5
    fib(4) => 3
    fib(3)    +      fib(2)  = 2   + 1
    fib(2) + fib(1) = 1 + 1
    2+1 = 3

    fib(3) => 2
    fib(2)  + fib(1)
    1 + 1 = 2
    '''

     

     

  • 相关阅读:
    字符串截取例子 大小写转换 拼接例子 把oc转成c语言
    字符串比较 是否相同 大小 创建字符串 例子
    数组于字典:把多个字典放到数组中
    考核7
    Delphi 单元不能被循环引用
    Delphi ADOQuery无法更新定位行问题(其它数据库访问控件类似)
    SQL远程服务器操作数据
    s​p​c​o​m​m​属​性​详​解
    dxSkinController动态调入皮肤
    RegisterClass与GetClass
  • 原文地址:https://www.cnblogs.com/hszstudypy/p/10851754.html
Copyright © 2020-2023  润新知