所谓递归函数,就是在函数内部调用了函数本身,这个函数就被成为递归函数。

为什么要调用自己呢?我们先来讲一讲数学中的归纳法,什么是数学归纳法呢?就是一个定理:

对于一个命题,

  1.n = 1 时,命题成立

  2.假设n = k时命题成立,那么n = k+1时命题也成立(m为任意自然数)

如果满足以上两点,那么就可以证明命题对任意自然数都成立

用通俗点的话讲就是假如前面一个成立能够得出后面一个成立的话,如果有一个开始,那么整个命题都成立

举一个简单的例子,我们都知道 1+2+3+....+n是等于= (1+n)*n/2

那么如何证明呢?

1.f(1) = (1+1)*1/2 = 1  正确

2.如果f(n) =(1+n)*n/2正确,那么f(n+!) = f(n)+n+1 = (1+n)*n/2 +n+1 = (n+2)(n+1)/2

可以证明公式成立,我们利用公式就可以用代码写出计算1到n的和的函数

def sum(n):
    #如果n=1时,结果为1
    if n ==1:
        return 1
    #如果f(n-1)的结果正确,那么f(n) = f(n-1)+n
    return sum(n-1)+n
print(sum(10))
--------------------------------
55

以上就是一个简单的递归函数。递归函数的基本原理就是这些,要熟练的使用递归运算需要自己的逻辑能力和多多的练习,我在举两个比较经典的有关递归的例子:

斐波纳契数列

斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55...这个数列从第3位开始,每一位都等于前两位之和,写一个函数,求出裴波那契数列的第n个数:

def fibonacci(n):
    #第一个数是1
    if n == 1:
        return 1
    #第二个数是1
    if n == 2:
        return 1
    #第n个数是 第n-1 和 第n-2个数的和
    return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
--------------------------------
55

执行的步骤大至如下:

可以看出,这个函数执行的次数大约为2**(n-3)  仅仅第10个数,函数就执行了100多次,可想而知这个函数的效率,所以虽然递归函数写起来非常方便,但还是要看情况使用,比如裴波那契数列我们使用for循环也可以实现:

def fibonacci(n):
    result1 = 0
    result2 = 0
    for i in range(1,n+1):
        if i == 1:
            result1 = 1
        if i == 2:
            result2 = 1
        result = result1 + result2
        result1 = result2
        result2 = result
    return result
        
print(fibonacci(10))
--------------------------
55

虽然逻辑看上去复杂一些,但是执行的效率却大大提高。

八皇后问题

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上

如果要满足条件,那么肯定是一行一个皇后,我们使用归纳法假设当放第n行时,满足上述条件,在放置第n+1行时需要满足与前n个皇后位置的列都不能相等,并且与前n个皇后的列差与行差不相等,如果可以放置,就再放置下一行。直到第8行可以放入一枚皇后后就表示成功,否则都表示失败,这部分用代码表示就是:

#这个函数传入一个列表,列表下标表示行,元素表示列,再传入一个防止到哪一行的位置参数
def queen(lis,pos=0):
    #假设前n-1行成立,开始第n行的摆放,从第一列开始测试
    for col in range(1,len(lis)+1):
        #将尝试摆放皇后
        lis[pos] = col
        flag = True
        #逐一与前n个皇后做判断
        for row in range(pos):
            #如果出现有冲突的皇后,就尝试摆放下一列
            if lis[row] == col or abs(col-lis[row]) == pos - row:
                flag = False
                break
        #如果皇后摆放没有问题,如果是最后一行了就输出,否则就开始摆放下一行的皇后
        if flag:
            if pos == 7:
                print(lis)
                return
            else:
                queen(lis,pos+1)
queen([0]*8)

八皇后问题本身算的上有一些复杂的算法,但是用递归函数后,可以发现执行代码还是比较简洁的,这就是递归的好处。