递归函数recursion
函数直接或者间接调用自身,这就是递归函数。能用递归函数解决的问题,一般使用循环也可以解决。递归函数一定要有边界
递归函数的案例
一、斐波那契数列
求斐波那契数列前n项
def fib(n): return 1 if n < 1 else fib(n - 1) + fib(n - 2) for i in range(5): print(fib(i), end=' ')
循环的写法
def fib(n): pre = 0 cur = 1 for i in range(n): pre, cur = cur, pre + cur print(cur, end=' ') fib(5)
二、阶乘
def fn(n): if n==1: return 1 return n * fn(n-1) print(fn(5))
循环的写法
def fn(n): result = n for i in range(1, n): result *= i return result print(fn(5))
三、幂
def p(x, y): if y == 0: return 1 return x * p(x, y - 1) print(p(3, 3))
循环的写法
def p(x, y): result = 1 for _ in range(y): result *= x print(result) p(3, 3)
四、二分查找
def search(seq, num, lower, upper): if lower == upper: assert num == seq[upper] return upper else: middle = (lower + upper) // 2 if num > seq[middle]: return search(seq, num, middle + 1, upper) else: return search(seq, num, lower, middle) # lst = [0,0,0,0,0,0] lst = [4, 25, 8, 23, 4, 100, 95] lst.sort() print(lst) print(search(lst, 0,0,0))
如果lower下限和upper上限相同,那么久可以断言这就是要查找数字所在的位置,直接返回即可。否则,先找出中间位置,再确定是在左半部分还是在右半部分,适用递归调用函数即可。
可以将代码的上限和下限参数给出默认值,这样就使代码更灵活
def search(seq, num, lower=0, upper=None): if upper is None: upper = len(seq) - 1 if lower == upper: assert num == seq[upper] return upper else: middle = (lower + upper) // 2 if num > seq[middle]: return search(seq, num, middle + 1, upper) return search(seq, num, lower, middle) lst = [34, 67, 8, 123, 4, 100, 95] lst.sort() print(lst) print(search(lst, 34))
递归函数的深度问题
Python对递归函数的深度做了限制,默认最大1000次,可以使用sys.getrecursionlimit()查询,使用sys.setrecursionlimit()进行修改
import sys
print(sys.getrecursionlimit())
结果
1000
如果超出了递归深度的限制,将跑出异常RecursionError: maximum recursion depth exceeded
def fn(): return fn() fn()
异常
File "C:/Users/ASUS-PC/PycharmProjects/函数.py", line 98, in fn return fn() RecursionError: maximum recursion depth exceeded
递归函数的性能
递归和循环的性能对比
递归的测试
import datetime start = datetime.datetime.now() n=25 def fib(n): return 1 if n < 2 else fib(n - 1) + fib(n - 2) for i in range(n): print(fib(n), end=' ') delta = (datetime.datetime.now() - start).total_seconds() print(delta)
运行结果
0.751987
循环的测试
import datetime start = datetime.datetime.now() pre = 1 cur = 1 for i in range(10000): pre, cur = cur, pre + cur print(cur,end=' ') delta = (datetime.datetime.now() - start).total_seconds() print(delta)
运行结果
0.048139
对于斐波那契数列的改进
def fib(n, pre=1, cur=1): pre, cur = cur, pre + cur print(cur, end=' ') if n == 2: return fib(n - 1, pre, cur) fib(300)
间接递归
通过其他函数调用自身,应该从代码规范上规避这种情况
def fn():
fn1()
def fn1():
fn()
fn()