chapter8.3、二分查找

二分查找

二分查找的前提是有序,有序的线性表,如果是字典,关键字有序

二分查找的时间复杂度是O(log n),在查找方法中是较常见的方法

假设有一个列表[37,99,73,48,47,63,35,37,37,37,90],先排序,再插入数字,使用python该怎样写呢,以下是一种解法

a = [37,99,73,48,47,63,35,37,37,37,90]
newlist = sorted(a)##先排序
def inster_sort(orderlist, num):
    ret = orderlist[:]
    start = 0
    end = len(ret)
    ##这里不能是len(ret)-1,如果要插入的数字大于最后一位,那么要返回的插入点要包含在范围内,不减一就能包含最后一个对象
    while start < end: #两端会逐渐逼近,最终会重合
        midpoint = (end + start) // 2  ##二分
        if ret[midpoint] > num:  
            end = midpoint  ##要插入的数小于中点,右侧左移
        else:
            start = midpoint+1  ##大于中点,左侧右移
    ret.insert(start, num)
    return ret
print(inster_rsort(newlist,100))##测试

 

当然,也可以反向倒排,原理相同,如下

a = [37,99,73,48,47,63,35,37,37,37,90]
newlist = sorted(a,reverse=True)
def inster_rsort(rorderlist,x):
    low = len(rorderlist)
    high = 0
    while high != low:
        mid = (high+low)//2
        if rorderlist[mid] > x:
            high = mid+1
        else:
            low = mid
    rorderlist.insert(high,x)
    return rorderlist
print(inster_rsort(newlist,100))##测试

 
当然,还可以写成递归版本,但是受递归深度限制,不推荐使用,效率也可能不好,有时间回来补递归版本!

 

bisect模块

bisect的函数有

bisect.bisect_left(a,x,lo=0,hi=len(a))  a是有序列表,x是要插入的对象,lo和hi指定区间,默认是整个区间,如果x存在,就返回x左边的index

bisect.bisect_right(a,x,lo=0,hi=len(a))  和上边相同,只是返回的插入点如果已存在,就返回插入点右边的index

bisect.insort_left(a,x,lo=0,hi=len(a))  有序列表a插入x,等同于a.insert(bisect.bisect_left(a,x),x)

bisect.insort_right()  x存在时,在右边插入,

默认的存在x时,都是右边插入

小练习

一批工件,标准尺寸是20-22(练习忽略单位)为A级,18-20和22-24为B级,其他为C级,使用该模块解决,要求不包括边界

import bisect
def get_gread(size):
    sizepoint = [18,20,22,24]
    greadlist = 'CBABC'
    if size<21:
        return greadlist[bisect.bisect_left(sizepoint,size)]
    else:
        return greadlist[bisect.bisect_right(sizepoint, size)]

 

posted on 2018-09-19 15:39  Riper  阅读(122)  评论(0编辑  收藏  举报

导航