递归
本章节前面已经介绍了关于函数创建和函数调用的知识,在函数中不仅可以调用其他函数,也可以调用函数本身。
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数,递归这个词对于没有接触过编程语言的读者来说会比较陌生,简单来说递归就是函数自己调用自己的过程。
读者可以尝试下面一个递归程序:
def recursion():
return recursion()
recursion()
运行后程序会直接崩溃,显示“超出最大的递归深度”结束程序的运行。这一类递
归被称为无穷递归,永远不会结束。这种递归是没有意义的,对我们没有用,不能帮助我们解决问题。有用的递归一般具有以下几个特性:
1.具有明确的结束条件
2.递归的调用次数是有限的
3.每一次更深层次的递归,都使得问题规模进一步减小
4.当问题规模到达一定程度时,递归效率不高,多次调用递归会导致栈溢出
经典案例
1.1阶乘
若求n(n为正整数)的阶乘,n的阶乘定义为n*(n-1)*(n-1)…*2*1。没有接触过递归的读者可能第一时间想到的就是用for循环求解。递归也可以解决阶乘的问题,而且代码量更少效率更高。
首先我们将递归公式写出来
下面直接利用递归直接实现阶乘的定义,并求4!
def factorial(n):
if(n==1):
return 1 #结束条件
else:
return n*factorial(n-1)
factorial(4)
运行结果:
24
递归的执行过程可以分为更小的两个过程:递“去”的过程,“归”回的过程。首先,递归会执行“去”的过程,在满足终止条件前,就会一直在函数内,带着更新的参数,调用函数自身。当满足终止条件后,便开始执行“归”回的过程,直到完成所有函数。下面通过流程图来详细讲解4!的递归过程
将正整数4带入函数factorial(n),n=4满足递归函数第二个条件,于是返回“return 4* factorial(4-1)”语句; “factorial(4-1)”我们不知道,于是就先求解factorial(3),此时n=3,满足递归函数第二个条件,于是返回语句“return 3* factorial(3-1)”语句;而“factorial(3-1)”我们也不知道,于是就先继续求解factorial(2),此时n=2, 满足递归函数第二个条件, 返回“return 2* factorial(2-1)”语句; 继续求解factorial(1),此时n=1,满足递归函数结束条件,直接返回数值1。这就是递归 “去”的过程
通过上面的分析,我们得到了factorial(1)的值,根据factorial(1)的值从而我们就可以得到factorial(2)的值,根据factorial(2)的值从而我们就可以得到factorial(3)的值,最终根据factorial(3)的值,我们得到factorial(4)的值,也就是4!的值。这就是递归的“来”过程。
1.2斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、……在数学上,根据数列中各个数之间的关系,得到斐波那契数列的递推公式:
使用递归实现斐波那契数列,并输出第10个斐波那契数的值。
def Fibonacci(n):
if(n==0):
return 0
elif(n==1):
return 1
else:
return Fibonacci(n-1)+Fibonacci(n-2)
Fibonacci(10)
运行结果:
55
1.3青蛙跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶,还可以一次跳3级台阶。求该青蛙跳上一个 n级的台阶总共有多少种跳法。
def step(n):
if(n<=0):
return 0
elif(n==1):
return 1
elif(n==2):
return 2
elif(n==3):
return 4
else:
return step(n-1)+step(n-2)+step(n-3)
step(7)
运行结果:
44
欢迎大家交流补充~