所谓递归函数,就是在函数内部调用了函数本身,这个函数就被成为递归函数。
为什么要调用自己呢?我们先来讲一讲数学中的归纳法,什么是数学归纳法呢?就是一个定理:
对于一个命题,
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)
八皇后问题本身算的上有一些复杂的算法,但是用递归函数后,可以发现执行代码还是比较简洁的,这就是递归的好处。