认识递归
1、什么是递归函数:
在自身函数里调用自己,就是递归函数,python系统默认最大递归次数为998次,超过了这个次数会报如下错误(RecursionError: maximum recursion depth exceeded while calling a Python object),写递归时一定要写结束条件!!
1.1、递归的返回值:
不要只看到return就认为已经返回了,要看返回操作是在递归到几层的时候发生的,然后返回给了谁
如果不是返回给外层函数,调用者就接收不到
需要再分析,看如何把结果返回回来
2、如何修改默认递归得次数:
不建议修改,如果递归次数太多就不适合用递归来解决
import sys
sys.setrecursionlimit(10000)
3、递归得优缺点:
优点:会让代码变简单
缺点:占内存
一个递归计算年龄的例子及递归得运行过程
需求:
求欧阳多大了
已知:欧阳比张三大两岁,
张三比李四大两岁,
李四比二麻子大两岁
二麻子今年40了
递归得代码:求欧阳今年多大了:
defage(n):if n == 4:return 40
elif n > 0 and n < 4:return age(n+1)+2
print(age(1)) #最终计算结果:46
上面得递归代码运行得过程:
第一次递归,执行函数时将1当实参传进来了def age(1):if 1 == 4:return 40
elif 1 > 0 and 1 < 4:return age(1+1)+2 #age(2+2 #44+2==46最终结果为:46
def age(2):if 2 == 4:return 40
elif 2 > 0 and 2 < 4:return age(2+1)+2 #age(3)+2 #42+2==44
def age(3):if 3 == 4:return 40
elif 3 > 0 and 3 < 4:return age(3+1)+2 #age(4)+2 #40+2==42
def age(4):if 4 == 4: #n==4时
return 40 #返回40
elif 3 > 0 and 3 < 4: #不符合这里得条件,一下代码不执行
return age(3+1)+2
画图说明执行过程:
一个递归计算斐波那契数列的例子及递归的过程
斐波那契数列说明(第一位和第二位都是1,以后的每个数字是前两个数字相加的合):1,1,2,3,5,8,13,21,34,55,89
1、使用双调用的形式计算斐波那契数列
deffib(n):if n == 1 or n == 2:return 1
return fib(n-1) +fib(n-2)print(fib(5))
1.1、递归方式
第一次递归的过程def fib(5):if n == 1 or n == 2: #向下递归 #向上预算结果
return 1
return fib(n-1) +fib(n-2) #fib(5-1) + fib(5-2) #3+2=5
print(fib(5)) #结果为5
第二次递归得过程def fib(4):if n == 1 or n == 2:return 1
return fib(n-1) +fib(n-2) #fib(4-1) + fib(4-2) #2+1=3
print(fib(4)) #结果为:3
def fib(3):if n == 1 or n == 2:return 1
return fib(n-1) +fib(n-2) #fib(3-1) + fib(3-2) #1+1=2
print(fib(3)) #结果为:2
第三次递归的过程def fib(3):if n == 1 or n == 2:return 1
return fib(n-1) +fib(n-2) #fib(3-1) + fib(3-2)
print(fib(3))def fib(2):if n == 1 or n == 2:return 1 #返回1
return fib(n-1) +fib(n-2)print(fib(2))def fib(1):if n == 1 or n == 2:return 1 #返回1
return fib(n-1) +fib(n-2)print(fib(1))
说明:双递归的方式计算斐波那契数列效率很慢,因为递归里设计到两次函数调用,每个函数每次调用都要重新计算一下,具体看下图详解
2、使用但调用的形式计算斐波那契数列
#一次调用计算斐波那契数列
deffib(n):if n == 2:return 1,1
else:
a,b= fib(n-1)print(a,b)return b,a+bprint(fib(4)) #结果为前一个数字和计算结果(不完美)
#修改后(只显示计算出的斐波那契数列 完美的)
def fib(n,l =[0]):
l[0]+=1
if n == 1 or n == 2:
l[0]-= 1
return 1,1
else:
a,b= fib(n-1)
l[0]-= 1
if l[0] ==0:return a+breturn b,a+bprint(fib(4))
2.1、递归过程说明:
deffib(n):if n == 2:return 1,1
else:
a,b= fib(n-1)print(a,b)return b,a+bprint(fib(4)) #最终结果为(2,3)
#第一次递归
def fib(4):if 4 == 2: #0、条件不成立
return 1,1
else:
a,b= fib(4-1) #1、4-1=3 #8、a=1,b=2
return b,a+b #9、返回值2,3
print(fib(4))#第二次递归
def fib(4):if 4 == 2: #2、条件不成立
return 1,1
else:
a,b= fib(4-1) #3、3-1=2 #6、a=1,b=1
return b,a+b #7、返回值1,2
print(fib(4))#第三次递归
def fib(4):if 4 == 2: #4、条件成立
return 1,1 #5、返回1,1
else:
a,b= fib(4-1)return b,a+bprint(fib(4))
算法
什么叫算法:计算的方法:人脑复杂,计算机简单
查找:找数据
排序:找最短路径
现在学习的算法都是过去式
了解基础的算法才能创造出更好的算法
不是所有的事情都能套用现成的方法解决的
有些时候用到学过的算法知识来解决新的问题
二分查找算法
二分查找算法,必须处理有序的列表
使用递归实现二分查找算法:
l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]def find(l,aim,start = 0,end =None):
end= len(l) if end is None elseend
mid_index= (end - start) // 2 +startif start <=end:if l[mid_index] aim:return find(l,aim,start=start,end=mid_index-1)else:return print('找到了,index为:%s'%mid_index,)else:return '找不到这个值...'ret= find(l,44)print(ret)
递归实现的过程
#第一次递归
def find(l,aim,start = 0,end =None):
end= len(l) if end is None else end #end = len(l) -->25
mid_index = (end - start) // 2 + start #计算中间值 25 // 2 == 12 + 0 == 12
if l[mid_index] < aim: #12和目标作比较,12 < 44
find(l,aim,start = mid_index+1,end=end) #find (l,44,start=13,end=24)
elif l[mid_index] >aim:
find(l,aim,start=start,end=mid_index-1)else:print('找到了',mid_index,aim)
find(l,44)#第二次递归
def find(l,aim,start = 0,end = None): #find(l,44,start = 13,end = 24)
end = len(l) if end is None else end #end 不等于空,所以end = 24
mid_index = (end - start) // 2 + start #计算中间值 (24 - 13) // 2 == 5 + 13 == 18
if l[mid_index] < aim: #18和目标作比较,l[18] == 67,67和44比较
find(l,aim,start = mid_index+1,end=end)elif l[mid_index] > aim: #67 > 44
find(l,aim,start=start,end=mid_index-1) #find (l,44,start=13,end=18 - 1)
else:print('找到了',mid_index,aim)#第三次递归
def find(l,aim,start = 0,end = None): #find(l,44,start = 13,end = 17)
end = len(l) if end is None else end #end 不等于空,所以end = 17
mid_index = (end - start) // 2 + start #计算中间值 (17 - 13) // 2 == 2 + 13 == 15
if l[mid_index] < aim: #15和目标作比较,l[15] == 55,55和44比较
find(l,aim,start = mid_index+1,end=end)elif l[mid_index] > aim: #55 > 44
find(l,aim,start=start,end=mid_index-1) #find (l,44,start=13,end=15 - 1)
else:print('找到了',mid_index,aim)#第四次递归
def find(l,aim,start = 0,end = None): #find(l,44,start = 13,end = 14)
end = len(l) if end is None else end #end 不等于空,所以end = 14
mid_index = (end - start) // 2 + start #计算中间值 (14 - 13) // 2 == 0 + 13 == 13
if l[mid_index] < aim: #13和目标作比较,l[13] == 42,42和44比较,42 <44
find(l,aim,start = mid_index+1,end=end) #find (l,44,start=14,end=14)
elif l[mid_index] >aim:
find(l,aim,start=start,end=mid_index-1)else:print('找到了',mid_index,aim)#第五次递归
def find(l,aim,start = 0,end = None): #find(l,44,start = 14,end = 14)
end = len(l) if end is None else end #end 不等于空,所以end = 14
mid_index = (end - start) // 2 + start #计算中间值 (14 - 14) // 2 == 0 + 13 == 13
if l[mid_index] < aim: #13和目标作比较,l[13] == 42,42和44比较,42 <44
find(l,aim,start = mid_index+1,end=end) #find (l,44,start=15,end=14) #start大于end时预示着找不到了
elif l[mid_index] >aim:
find(l,aim,start=start,end=mid_index-1)else:print('找到了',mid_index,aim)