Python学习之Part23.初识递归

1.初识递归函数

1.什么是递归函数:
 在函数内部有直接或间接调用函数本身的函数就是递归函数,例如:

def fun_test():
    return fun_test()	# 在函数内部调用函数本身
fun_test()

当然,执行这段代码时会出现报错:
RecursionError: maximum recursion depth exceeded
翻译过来就是:递归错误:超出最大递归深度,同时会出现如下提示:
在这里插入图片描述从这里我们可以看出:调用超过996/997次就会出现报错,因此,python中默认的递归深度不超过1000,这是为了保护内存,当然,我们也可以自己修改递归深度,修改递归深度的方法如下:

import sys
sys.setrecursionlimit(100000)	# 参数就是你想要的递归深度

但是不建议自己修改递归深度,因为如果递归次数过多,那就说明不适合使用递归实现。
递归的优势在于:减少代码的冗余,让代码更简洁。
递归的缺点在于:占内存

2.递归函数的执行

递归二字,其实可以分开来解读,即:传递过程回归过程,传递过程就是函数的调用过程,回归过程就是返回值返回的过程,我们使用一个例子来进行说明:

def age(n):
    if n==4:
        return 30
    elif n>0 and n<4:
        return age(n+1)+2	# 在此处调用了函数本身
print(age(1))

此函数的执行过程如下所示:
在这里插入图片描述

3.递归函数的实例 - 二分查找算法

如果我们需要在数组中查询一个数,即:输入数字,返回此数字在数组中的下标,最简单也是最容易想到的方法就是遍历数组,但是遍历也是最耗时的方法,如果有100w个数,而我们所需查找的数刚好是最后一个,那我们就需要循环100w次才能找到。

二分查找算法的思想是:
 对于一个有序的数组,设置最开始的搜索区间是整个数组,区间左端点为0,右端点是数组长度,取搜索区间的中间值,将所要查找的值与中间值进行比较,如果刚好相等,那么一次就找到了;如果比中间值大,那说明我们所需查找的值在右边,那么我们将区间左边往右移动,即将区间左端点设置为中间值的索引,此时搜索区间长度就缩短为原来的一半,同理,如果比中间值小,那说明我们所需查找的值在左边,那么我们将区间右边往左移动,即将区间右端点设置为中间值的索引,再在新的搜索区间重复上面步骤进行查找,知道找到为止。

实现代码如下:

def binary_serarch(l,aim,start_index=0,end_index=None):
    '''
    函数用来实现二分查找固定的值
    :param l: l 是原始的参数,需要注意的是 l 的值需要一直保持不变,否则下标就会改变了
    :param aim: aim 是需要查找的目标
    :param start_index: 从 l 中开始查找的下标
    :param end_index: 从 l 中结束查找的下标位置
           需要注意的是,此值默认是None,本来应该是列表l的长度,但是不能直接 end_index = len(l)
           来设置默认值,因为 l 不是一个已知的,它是一个未知的参数,所以此值应该默认为None再重新赋值
    :return:
    '''
    end_index = len(l) if end_index is None else end_index
    # 如果是第一次调用的默认参数则将搜索区间右边设置为数组长度,否则维持原值不变
    # 即,第一次搜索区间为整个数组
    mid_index = (end_index-start_index)//2 + start_index    # 此值是中间下标
    if start_index <= end_index:  # 如果开始的下标小于结束的下标,说明还有寻找的空间,则继续寻找
        if l[mid_index]>aim:    # 如果列表中间的值比目标值大,说明目标值在左边
            return binary_serarch(l,aim,start_index=start_index,end_index=mid_index-1)
            # 那么将搜素区间结束位置左移,由于 l[mid_index] 已经做过比较,因此不再做比较,下标值减一
            # 注意已经要 return,否则递归到此处没有接收返回值会返回None
            # 注意,不需要改变的参数也要传递,不传参会有默认参数...
        if l[mid_index]<aim:    # 如果列表中间的值比目标值小,说明目标值在右边
            return binary_serarch(l,aim,start_index=mid_index+1,end_index=end_index)
        else:   # 如果中间值与aim相等,则直接返回
            return mid_index
    else:   # 如果开始的下标小于结束的下标,说明已经全部搜索完毕且没找到,则返回一个字符串
        return 'No such number.'

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]
ret = binary_serarch(l,30)
print(ret)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值