递归函数
定义: 自己调用自己的函数
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行,自己调用自己,代码暂定在digui(n-1)所在行,发生阻塞 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) 回到参数为2的第12行 代码继续向下执行, print(2) print(3) 回到参数为3的第12行 代码继续向下执行, print(3) print(4) 回到参数为4的第12行 代码继续向下执行, print(4) print(5) 回到参数为5的第12行 代码继续向下执行, print(5) 5 4 3 2 1 0 0 1 2 3 4 5 '''
2.
'''
栈帧空间 : 负责运行函数而开辟的空间
(1)递归函数整体过程: 调用一层函数就是开辟一层栈帧空间,结束一层函数,就是释放一层栈帧空间,
递归函数实际上就是开辟和释放栈帧空间的过程
(2)递归函数回的过程: 如果函数走到最后一层执行结束了,要回到上一层空间函数调用处,继续向下执行,直到所有代码执行完毕,
在触发触底反弹操作,回到上一层空间函数调用处,以此类推...
直到所有的函数全都释放掉,那么这个递归函数彻底终止.
(3)写递归函数的时候切记要加上一个终止的条件,否则会发生内存溢出,如果层数过多,不推荐使用递归.
'''
''' 栈帧空间 : 负责运行函数而开辟的空间 (1)递归函数整体过程: 调用一层函数就是开辟一层栈帧空间,结束一层函数,就是释放一层栈帧空间, 递归函数实际上就是开辟和释放栈帧空间的过程 (2)递归函数回的过程: 如果函数走到最后一层执行结束了,要回到上一层空间函数调用处,继续向下执行,直到所有代码执行完毕, 在触发触底反弹操作,回到上一层空间函数调用处,以此类推... 直到所有的函数全都释放掉,那么这个递归函数彻底终止. (3)写递归函数的时候切记要加上一个终止的条件,否则会发生内存溢出,如果层数过多,不推荐使用递归. '''
3.
递归函数通过两个条件出发回的过程: (1) 当前函数彻底执行完毕的时候,触发回的过程,回到上一层函数的调用处 (2) 当前函数遇到return 返回值的时,触发回的过程,回到上一层函数的调用处 '''
# (1)计算任意数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) # 5*4*3*2*1 def jiecheng(n): if n<=1 : return 1 return n * jiecheng(n-1) # jiecheng(1) => 1 res = jiecheng(5) print(res) ''' # 代码解析: 去的过程: 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 * jiechneg(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 * jiecheng(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
4.尾递归: 只返回递归函数本身且非表达式(没有运算(+-*/..))
''' 只开辟一个栈帧空间完成递归函数(因为最终的返回值就是第一层空间的返回值,所以只需要一层栈帧空间即可,不停的进行替换) 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 jiecheng2(n,endval): if n<=1 : return endval return jiecheng2(n-1,n*endval) # 给用户用 不需要用户填写第二个参数(比较人性化) def jiecheng3(n): return jiecheng2(n,1) res = jiecheng3(5) print(res)
4.斐波那契数列
除了前2个 ,后面每一个值都是上一个数 + 上上的数 两者之和 def fib(n): if n ==1 or n==2: return 1 return fib(n-1) + fib(n-2) res = fib(5) 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) fib(2)+fib(1)=1+1=2 + 1 2+1 = 3 fib(3) =>2 fib(2) + fib(1) 1 + 1 = 2 '''