hopeless-dream

导航

Python中的递归函数

递归函数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()

 

posted on 2020-11-01 14:06  hopeless-dream  阅读(219)  评论(0编辑  收藏  举报