查找算法之二分查找(折半查找)Python

查找算法之二分查找(折半查找)

对于顺序表中已经排好序的表来说,除了上篇文章中的可以比较大小外,还可以有另外一种思路,就是二分查找。因为已经排好序了,可以直接比较中间值(中位数),如果中位数比要查找的数大,那么要查找的数可能在前半部分(至少不可能在后半部分),因为后半部分一定比中位数大,也一定比要查找的数大。继续,把前半部分当做一个新的有序表,进一步比较中位数,直到找到要查找的数或者不存在。

def binary_search(alist, item):

    first = 0
    last = len(alist) - 1
    mid = 0
    found = False
    
    while first <= last and not found:
        mid = (first + last) // 2
        if alist[mid] == item:
            found = True
        elif alist[mid] < item:     # 说明item一定在当前列表的后半部分,所以筛选范围向后移动
            first = mid + 1
        else:
            last = mid - 1     # 一定在前半部分

    if found:
        return mid
    else:
        return False

# 注意列表一定是有序的。
testlist = [0,1,2,8,13,17,19,32,42]
print(binary_search(testlist, 32))
print(binary_search(testlist, 17))

当然也可以用递归的形式做,在前面叙述中可以看出来,每次分割后,都把要比较的子列表当做一个新的列表进一步比较,其实这就是递归的过程。因为递归每次的变量都会重复,这里如果要输出要查找元素的下标,需要注意。

# 二分查找的递归形式
def binary_search(alist, item):
    first = 0
    last = len(alist) - 1

    if first <= last:

        mid = (first + last) // 2
        if alist[mid] == item:
            # 注意返回的mid是此时的first和last的中间值
            return mid
        elif alist[mid] < item:
            # 注意,因为本函数中每次都是初始化first和last
            # 所以递归调用时,返回的miid是当前子列表的中间值
            # 要想得到原始的中间值,需要起始位置
            first = mid + 1
            return first + binary_search(alist[first:], item)
        else:
            # 此时的开始的相对位置没有改变,改变的只是结束位置
            # 而结束位置并不影响子列表的中间值的相对原来的位置
            # 所以此处不需要加上起始位置first。
            last = mid - 1
            return binary_search(alist[:last+1], item)
    else:
        return False

testlist = [0,1,2,8,13,17,19,32,42]
print(binary_search(testlist, 13))
print(binary_search(testlist, 8))

接下来再看一下时间复杂度。每一次比较,那么剩下的还需要比较的就是n/2个元素(最坏的情况下),做第二次比较时,还剩下n/4个元素,也就是n/(2^i)
如果还剩一个元素时,就只需要比较一次就知道结果了,所以n/(2^i)=1时就是最终结束时,可以看出来i=log(n),成对数形式的复杂度,比线性的复杂度要低一点,优化了一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值