递归函数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= 0cur= 1
for i inrange(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=nfor i in range(1, n):
result*=ireturnresult
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 _ inrange(y):
result*=x
print(result)
p(3, 3)
四、二分查找
def search(seq, num, lower, upper):if lower ==upper:
assert num==seq[upper]returnupperelse:
middle= (lower + upper) //2
if num >seq[middle]:return search(seq, num, middle + 1, upper)else:returnsearch(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 isNone:
upper= len(seq) - 1
if lower ==upper:
assert num==seq[upper]returnupperelse:
middle= (lower + upper) //2
if num >seq[middle]:return search(seq, num, middle + 1, upper)returnsearch(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():returnfn()
fn()
异常
File "C:/Users/ASUS-PC/PycharmProjects/函数.py", line 98, infnreturnfn()
RecursionError: maximum recursion depth exceeded
递归函数的性能
递归和循环的性能对比
递归的测试
import datetime
start=datetime.datetime.now()
n=25def fib(n):return 1 if n < 2 else fib(n - 1) + fib(n - 2)for i inrange(n):
print(fib(n), end=' ')
delta= (datetime.datetime.now() -start).total_seconds()
print(delta)
运行结果
0.751987
循环的测试
import datetime
start=datetime.datetime.now()
pre= 1cur= 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:returnfib(n- 1, pre, cur)
fib(300)
间接递归
通过其他函数调用自身,应该从代码规范上规避这种情况
def fn():
fn1()
def fn1():
fn()
fn()