用python对二分查找的递归实现和非递归实现

文章详细介绍了如何在Python中实现二分查找算法,首先展示了非递归的方法,通过迭代更新查找范围来定位目标元素,然后讨论了递归实现,分析了初始代码为何返回None,并给出了修正后的递归版本,强调了递归调用的返回和边界条件的重要性。
摘要由CSDN通过智能技术生成

      一 、首先说说非递归实现 

        二分查找就是从一个有序数列中查找指定的元素,其思想是:首先用序列中间位置的元素和要查找的元素进行比较,如果大于要查找的元素,说明要查找的元素位于前半部分,如果小于要查找的元素,说明位于后半部分,如果等于要查找的元素,说明找到了,返回索引位置。然后再对前半部分(或后半部分)进行同样的操作。具体如下:

        假定要查找的元素所在的序列如下:

list01 = [0,1,2,3,4,5,6,7,8,9]

        接下来我们定义两个变量(l,r)分别用来存储第一个元素的索引和最后一个元素的索引。如下:

l,r = 0,len(list_target)-1  # list_target为传入的列表

       再定义一个变量存储中间位置(mid),如下:

mid = (l+r) // 2

        接下来我们只要用mid位置的元素与要查找的元素进行比较就可以了。非递归实现的代码如下:

def binary_search2(list_target,num):
    #1.定义l,r分别代表首位、末尾元素索引
    l,r = 0,len(list_target) - 1
    while l <= r:
        mid = (l+r) // 2
        #2.判断中间元素是否是要查找的num
            #如果中间元素大于num,说明num存在于前半部分,否则,存在于后半部分
        if list_target[mid] > num :
            #存在前半部分中,则把r更新一下,向前移动一位
            r = mid - 1
        elif list_target[mid] < num:
            #存在后半部分中,则把l更新一下,向后移动一位
            l = mid + 1
        elif list_target[mid] == num:
            #找到了,返回索引位置
            return mid
    else:
        #没有找到,返回0
        return 0

        测试:

print(binary_search(list01,6))

        运行结果为:6,查找正确。

        需要补充说明的是,while循环判断l小于等于r是个大前提,如果l一直增加或r一直减小到条件不满足时还没有找到元素,说明要查找的数据不存在,此时l大于r。

       二、接下来说说递归实现

        看到二分查找,首先我想到的是用递归实现,本来以为递归实现起来应该更简单,但却出现了一些意想不到的结果,总是返回None,后面查了python函数调用的原理,才修改过来。

        首先我想到的是传入的参数代表查找的范围变化,也需要l,r分别代表首末元素的索引,原始序列数据和要查找的数据也是需要传入的,所以函数定义为:

    binary_search(list_target,l,r,num)

        接下来用中间位置mid = (l+r)//2 的元素与要查找的元素进行比较,如果大于或小于,则调用函数自身(此时l和r则发生变化),如果等于,则返回索引。代码如下:

def binary_search(list_target,l,r,num):
    mid = (l+r) // 2
    if list_target[mid] == num:
        return mid
    if list_target[mid] > num:
        binary_search(list_target,l,mid-1,num)
    elif list_target[mid] < num:
        binary_search(list_target,mid+1,r,num)

        进行测试如下:

list01 = [0,1,2,3,4,5,6,7,8,9]
print(binary_search(list01,0,len(list01)-1,5))

        发现返回结果为None.

        这个问题困扰了我好一会儿,通过调试我发现mid的值会变成要查找元素的索引“5”,感觉应该是调用那里出了问题。查找了相关资料发现,python函数调用的时候要开栈帧,调用结束栈帧就销毁了,所以在调用前加上return,实现层层返回结果,就可以了。此外,以上代码没有考虑到要查找元素不存在的情况,需要对l和r进行比较判断,修改后的完整代码如下:

def binary_search(list_target,l,r,num):
    if l > r:
        return 0
    mid = (l+r) // 2
    if list_target[mid] == num:
        return mid
    if list_target[mid] > num:
        return binary_search(list_target,l,mid-1,num)
    elif list_target[mid] < num:
        return binary_search(list_target,mid+1,r,num)

        总结:递归程序简洁易懂,但在调用过程中确实存在意想不到的情况,还要考虑递归的深度是否超过最大深度,如果数据序列很长时,就可能会超过调用深度,使用时还是要细心检查才好。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值