数据结构与算法----二分查找(Python版)

在顺序查找中,如果第1个数据项不匹配查找项的话,那最多还有n-1个待比对的数据项

那么,有没有方法能利用有序表的特性,迅速缩小待比对数据项的范围呢?

我们从列表中间开始比对!

如果列表中间的项匹配查找项,则查找结束如果不匹配,那么就有两种情况:

列表中间项比查找项大,那么查找项只可能出现在前半部分

列表中间项比查找项小,那么查找项只可能出现在后半部分

无论如何,我们都会将比对范围缩小到原来的一半:n/2

继续采用上面的方法查找

每次都会将比对范围缩小一半

 

def binarySearch(alist, item):
    first = 0
    last = len(alist) - 1
    found = False

    while first <= last and not found:
        midpoint = (first + last) // 2
        if alist[midpoint] == item:
            found = True
        else:
            if item < alist[midpoint]:
                last = midpoint
            else:
                first = midpoint
    return found

testList = [1,4,2,65,6,3,5,77,34]
print(binarySearch(testList,2))
print(binarySearch(testList,666))

 

二分查找算法实际上体现了解决问题的典

型策略:分而治之

将问题分为若干更小规模的部分通过解决每一个小规模部分问题,并将结果汇总得到原问题的解

 

显然,递归算法就是一种典型的分治策略算法,二分法也适合用递归算法来实现

 

def binarySearch(alist, item):
    if len(alist) == 0:
        return False
    else:
        midpoint = len(alist)//2
        if alist[midpoint] == item:
            return True
        else:
            if item < alist[midpoint]:
                return binarySearch(alist[:midpoint],item)
            else:
                return binarySearch(alinst[midpoint:],item)
            
testList = [1,4,2,65,6,3,5,77,34]
print(binarySearch(testList,2))
print(binarySearch(testList,666))

由于二分查找,每次比对都将下一步的比对范围缩小一半

每次比对后剩余数据项如下表所示:

二分查找:算法分析

当比对次数足够多以后,比对范围内就会仅剩余1个数据项

无论这个数据项是否匹配查找项,比对最终都会结束,解下列方程:

得到:i=log2(n)

所以二分法查找的算法复杂度是O(log n)

虽然我们根据比对的次数,得出二分查找的复杂度O(log n)

但本算法中除了比对,还有一个因素需要 注意到:

binarySearch(alist[:midpoint],item)这个递归调用使用了列表切片,而切片操作的复杂度是O(k),这样会使整个算法的时间复杂度稍有增加;当然,我们采用切片是为了程序可读性更好,实际上也可以不切片,而只是传入起始和结束的索引值即可,这样就不会有切片的时间开销了。

另外,虽然二分查找在时间复杂度上优于顺序查找

但也要考虑到对数据项进行排序的开销

如果一次排序后可以进行多次查找,那么排序的开销就可以摊薄但如果数据集经常动,查找次数相对较少,那么可能还是直接用无序表加上顺序查找来得经济

所以,在算法选择的问题上,光看时间复杂度的优劣是不够的,还需要考虑到实际应用的情况。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值