Files
python-book/01.基础语法/08.递归函数.md
2025-09-11 09:47:09 +08:00

140 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 递归函数
## 初识递归
* 递归的定义——在一个函数里再调用这个函数本身
* 递归的最大深度——997
```python
def foo(n):
print(n)
n += 1
foo(n)
foo(1)
```
997是python为了我们程序的内存优化所设定的一个默认值我们当然还可以通过一些手段去修改它。
```python
import sys
print(sys.setrecursionlimit(10000))
def foo(n):
print(n)
n += 1
foo(n)
foo(1)
```
将python允许的递归深度设置为了1w至于实际可以达到的深度就取决于计算机的性能了。
不推荐修改这个默认的递归深度因为如果用997层递归都没有解决的问题是不适合使用递归来解决。
## 汉诺塔问题
从左到右 A B C 柱 大盘子在下, 小盘子在上, 借助B柱将所有盘子从A柱移动到C柱, 期间只有一个原则: 大盘子只能在小盘子的下面.
我们只需要考虑如果有64层先将A柱上的63层移动到B柱上然后将A柱的第64个移动到C柱上然后将B柱上的63层移动到C柱上即可。
那怎么把63层都移到B柱上这个问题可以用上面相同的方法解决。
```python
def move(n,a,b,c):
if n == 1:
print(a,'->',c)
else:
# 将n-1个盘子从a --> b
move(n-1,a,c,b)
# 将剩余的最后一个盘子从a --> c
print(a,'->',c)
# 将剩余的n-1个盘子从 b --> c
move(n-1,b,a,c)
n = int(input('请输入汉诺塔的层数:'))
move(n,'A','B','C')
```
递归实现三级菜单
```python
menu = {
'山东': {
'青岛': ['四方', '黄岛', '崂山', '李沧', '城阳'],
'济南': ['历城', '槐荫', '高新', '长青', '章丘'],
'烟台': ['龙口', '莱山', '牟平', '蓬莱', '招远']
},
'江苏': {
'苏州': ['沧浪', '相城', '平江', '吴中', '昆山'],
'南京': ['白下', '秦淮', '浦口', '栖霞', '江宁'],
'无锡': ['崇安', '南长', '北塘', '锡山', '江阴']
},
'浙江': {
'杭州': ['西湖', '江干', '下城', '上城', '滨江'],
'宁波': ['海曙', '江东', '江北', '镇海', '余姚'],
'温州': ['鹿城', '龙湾', '乐清', '瑞安', '永嘉']
},
'安徽': {
'合肥': ['蜀山', '庐阳', '包河', '经开', '新站'],
'芜湖': ['镜湖', '鸠江', '无为', '三山', '南陵'],
'蚌埠': ['蚌山', '龙子湖', '淮上', '怀远', '固镇']
},
'广东': {
'深圳': ['罗湖', '福田', '南山', '宝安', '布吉'],
'广州': ['天河', '珠海', '越秀', '白云', '黄埔'],
'东莞': ['莞城', '长安', '虎门', '万江', '大朗']
},
'测试': {}
}
def threeLM(dic):
while True:
for k in dic:print(k)
key = input('input>>').strip()
if key == 'b' or key == 'q':return key
elif key in dic.keys() and dic[key]:
ret = threeLM(dic[key])
if ret == 'q': return 'q'
threeLM(menu)
# l = [menu]
# while l:
# for key in l[-1]:print(key)
# k = input('input>>').strip() # 北京
# if k in l[-1].keys() and l[-1][k]:l.append(l[-1][k])
# elif k == 'b':l.pop()
# elif k == 'q':break
```
## 二分查找算法
如果想在列表中查找某个数字,可以排序后从中间开始查找
![图片](08.递归函数/1.png)
```python
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 func(l,aim):
# mid = (len(l)-1)//2
# if l:
# if aim > l[mid]:
# func(l[mid+1:],aim)
# elif aim < l[mid]:
# func(l[:mid],aim)
# elif aim == l[mid]:
# print("找到了",mid)
# else:
# print('找不到')
# func(l,66)
# func(l,6)
def search(num,l,start=None,end=None):
start = start if start else 0
end = len(l)-1 if end is None else end
mid = (end - start)//2 + start
if start > end:
return None
elif l[mid] > num :
return search(num,l,start,mid-1)
elif l[mid] < num:
return search(num,l,mid+1,end)
elif l[mid] == num:
return mid
ret = search(18,l)
print(ret)
```