递归函数
一、定义
在函数中调用自身函数,就称改函数为递归函数
二、递归的特点
1、python从内存角度出发做了限制,递归的大递归深度默认是997/998
- 可以手动修改python参数来改变该限制
# import sys
# sys.setrecursionlimit(max_recursion)
2、递归的优缺点
- 递归的缺点 : 占内存
- 递归的优点: 会让代码变简单
三、初识递归
# 需求
# A 年龄多大?
# A 比 B 大两岁
# B 年龄多大?
# B 比 C 大两岁
# C 年龄多大?
# C 比 D 大两岁
# D 年龄多大?
# D今年40岁
# 分析:
A ——> n = 4 age(4) = age(3)+2 = age(n-1) + 2
B ——> n = 3 age(3) = age(2) + 2 = age(n-1) +2
C ——> n = 2 age(2) = age(1) + 2 = age(n-1) +2
D ——> n = 1 age(1) = 40
# 代码实现
def find_age(n):
if n == 1:
return 40
else:
return find_age(n-1)+2
print(find_age(4))
>>> 46
# 代码分解
# 第一次传输参数n = 4
def find_age(4):
if 4 == 1: # False
return 40
else:
return find_age(4-1)+2 # ==> find_age(3)+2
# 第一次传输参数n = 3
def find_age(3):
if 3 == 1: # False
return 40
else:
return find_age(3-1)+2 # ==> find_age(2)+2
# 第一次传输参数n = 2
def find_age(2):
if 2 == 1: # False
return 40
else:
return find_age(2-1)+2 # ==> find_age(1)+2
# 第一次传输参数n = 1
def find_age(2):
if 1 == 1: # True
return 40
else:
return find_age(n-1)+2
# 最终返回值的走向:
return find_age(1)+2 ===> 40+2 = 42
return find_age(2)+2 ===> 42+2 = 44
return find_age(3)+2 ===> 44+2 = 46
四、递归进阶——二分法查找
1、二分法查找(折半搜索法)原理
折半搜索是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。这种搜索算法每一次比较都使搜索范围缩小一半。
2、简单二分法查找实现
# 该方法可以基本实现查找,但是有个问题就是lst的值会随着递归的执行而改变,所以无法得到查找值所在原列表中的索引值
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 simple_binary_search(lst,target):
mid_index = len(lst)//2
if lst:
if lst[mid_index] > target:
return simple_binary_search(lst[:mid_index],target)
elif lst[mid_index] < target:
return simple_binary_search(lst[mid_index+1:],target)
elif lst[mid_index] == target:
return ('找到了!所查找的值为:{}'.format(lst[mid_index]))
else:
return ('对不起,没有您要查找的值!')
print(simple_binary_search(l,66))
3、升级版二分法查找实现
# 该方法解决了简单二分法查找中不能得到目标数在原列表中的索引问题,解决方式是每次不改变传入的列表,而是将索引进行改变,从而达到缩减搜索列表长度的目的
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 senior_binary_search(lst,target,start=None,end=None):
start = 0 if start is None else start
end = len(lst) if end is None else end
mid_index = start + (end - start)//2
if lst:
if lst[mid_index] > target:
return senior_binary_search(lst,target,start,mid_index-1)
elif lst[mid_index] < target:
return senior_binary_search(lst,target,mid_index+1,end)
elif lst[mid_index] == target:
return ('找到了!所查找的值为:{},所在索引为:{}'.format(lst[mid_index],mid_index))
else:
return ('对不起,没有您要查找的值!')
print(senior_binary_search(l,66))
五、递归扩展
# 1、 斐波那契 —— 问第n个斐波那契数是多少?
def fibonacci(n):
if n == 0 or n == 1:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(0))
print(fibonacci(1))
print(fibonacci(2))
>>> 1
>>> 1
>>> 2
# 阶乘 n!
def factorial(n):
if n == 0:
return 1
else:
return factorial(n-1)*n
print(factorial(0))
print(factorial(1))
print(factorial(2))
print(factorial(3))
>>> 1
>>> 1
>>> 2
>>> 6
# 多级菜单——递归
menu = {
'黑龙江省': {
'哈尔滨市': {
'松北区': {},
'道里区': {},
'南岗区': {},
'香坊区': {}
},
'齐齐哈尔市': {
'龙沙区': {},
'建华区': {},
'铁锋区': {},
},
'牡丹江市': {
'爱民区': {},
'东安区': {},
'阳明区': {},
}
},
'吉林省': {
'长春市': {
'南关区': {},
'宽城区': {},
'二道区': {},
},
'吉林市': {
'船营区': {},
'昌邑区': {},
}
},
'辽宁省': {
'沈阳市': {
'沈河区': {},
'和平区': {},
'皇姑区': {},
},
'大连市': {
'西岗区': {},
'中山区': {},
}
}
}
def recursion(dic):
while True:
for k in dic:
print(k)
user_input = input('输入内容(输入Q或q退出,输入B或b返回上一级):\n>>>').strip()
if user_input.lower() == 'b' or user_input.lower() == 'q':
return user_input
elif user_input in dic.keys() and dic[user_input]:
res = recursion(dic[user_input])
if res == 'q':
return 'q'
elif (not dic.get(user_input)) or (not dic[user_input]) :
continue
recursion(menu)