递归和二分法

1. 什么是递归

递归实际上函数的递归,而函数递归就是函数嵌套调用的一种特殊方式

具体是指:在调用一个函数的过程中又直接或间接的调用了函数本身

1.1 直接调用

举例 : 在调用func1的过程中,又调用了func1,这就是直接调用函数本身

def func1():
    print("我是func1====>")
    func1()
    
func1()
# 首先调用func1,然后函数体内部代码再调用func1,虽然局部作用域中没有func1这个名字,但是可以从全局
# 作用域获得

image-20201207190340703

1.2 间接调用

举例 : 在调用func1的过程中,又调用了func2,func2中又调用func1 , 这就是间接调用

def func1():
    print("我是func1====>")
    func2()
    
    
def func2():
    print("我是func2====>")
    func1()
    
    
    
func1()

image-20201207191035907

递归就是在自己调用自己,实际上递归的本质就是循环

2. 一段代码的循环执行

之前我们讲过循环的两种方式,一种while循环,一种for循环,现在又多了一种方式,就是递归

2.1 方式一

while True:
    print(1111)
    print(2222)
    print(3333)
    
# 在循环体中放入要循环的代码

2.2 方式二

def func():
	print(1111)
	print(2222)
	print(3333)    # 函数体中写入要循环执行的代码
	func()
    
    
func()

2.3 注意

递归可以实现的while True都可以实现

递归不能无限循环下去,因为递归是在调用函数,你调用函数就要创建局部名称空间用来存放名字,如果你一直递

归,也就是要一直创建名称空间,会消耗大量的内存,如果不加以限制,会造成内存溢出。所以应该在满足某种

条件下,结束递归,即结束函数的调用。

#1. 可以使用sys.getrecursionlimit()去查看递归深度,默认值为1000,虽然可以使用
# sys.setrecursionlimit()去设定该值,但仍受限于主机操作系统栈大小的限制

#2. python不是一门函数式编程语言,无法对递归进行尾递归优化。
#尾递归优化就是在调用下一次自己的时候,把上一次调用产生的名称空间回收了,但是python做不到

3. 回溯和递推

我们将用一个小学算年龄的问题来解释递归的原理和使用

# 问题:
有五个人,问第5个人他说我比第4个人大5岁,问第4个人他说我比第3个人大5岁,问第3个人他说我比第2个人大5岁,问第2个人他说我比第1个人大5岁,问第1个人他说他10岁,问1,2,3,4,5各几岁?

伪代码:

age(5) = age(4) + 5
age(4) = age(3) + 5
age(3) = age(2) + 5
age(2) = age(1) + 5
age(1) = 10

总结:age(n) = age(n-1) + 5

在回溯阶段,要求第n个人的年龄,需要回溯得到(n-1)个人的年龄,以此类推,直到得到第一个人的年龄,此

时,age(1)已知,因而不必再向前回溯了。然后进入递推阶段:从第一个人的年龄可以推算出第二个人的年龄

15,从第二个人的年龄可以推算出第三个人的年龄20,以此类推,一直推算出第五个人的年龄30为止,递归结

束。需要注意的一点是,递归一定要有一个结束条件,这里n=1就是结束条件。

def age(n):
    if n == 1:
        return 10
    return age(n-1) + 5


#   return age(1) + 5 + 5 + 5 + 5

image-20201207195448639

递归的应用场景

当你遇到一种需求中 , 有功能是需要简单的重复实现的话 , 就可以把这这个功能定义一个函数 , 然后在内部自己调

用自己 , 实现功能的重复

4. 小练习

使用递归迭代打印出列表中的所有值

l = [1, 2, 3, [1, 2, [1, 2, [4, 5, 6, [7, 8, [10, 11, 12, [13, 14, 15],7,8,9],18,20],21]]]]


def func(l):
    for i in l:
        if type(i) == list:
            l = i
            func(l)
        else:
            print(i)

func(l)

5. 二分法

二分法是一种算法,所谓算法就是一种高效解决问题的方法,二分法常用来快速查找数据

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 999, 11, 12, 13, 14]


def binary_search(find_num, l):
    print(l)
    if not len(l):
        print('要找的值不存在')
        return
    mid_val_index = len(l) // 2
    mid_val = l[mid_val_index]          # 当列表为空,再用索引取值就报错
    if find_num > mid_val:
        # 接下来的查找应该是在列表的右半部分
        l = l[mid_val_index + 1:]       # 切片超出索引会得到有个空列表
        binary_search(find_num, l)
    elif find_num < mid_val:
        # 接下来的查找应该是在列表的左半部分
        l = l[:mid_val_index]
        binary_search(find_num, l)
    else:
        print('find it')



binary_search(999, lst)
# 如果你遍历要找9次,但是二分法,3次就找到了
原文地址:https://www.cnblogs.com/xcymn/p/14107791.html