python bisect数组二分查找算法
什么是二分查找?
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。
要求:元素必须按顺序排列,升序/降序 都可
基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x
代码示例:
def bin_search(data_list, val): low = 0 # 最小数下标 high = len(data_list) - 1 # 最大数下标 while low <= high: mid = (low + high) // 2 # 中间数下标 //向下取整 if data_list[mid] == val: # 如果中间数下标等于val, 返回 return mid elif data_list[mid] > val: # 如果val在中间数左边, 移动high下标 high = mid - 1 else: # 如果val在中间数右边, 移动low下标 low = mid + 1 return # val不存在, 返回None ret = bin_search(list(range(1, 10)), 3) print(ret)
举例说明:
data_list = [1, 3, 5, 7, 9, 11, 13] val = 3
最小下标low=0, 最大下标high=len(data_list)-1==6,中间数下标mid=(low+high)//2==3,列表分为两部分,左列表==[1, 3, 5] 右列表==[9, 11, 13], 中间数mid_num=data_list[3]==7
val != mid_num且val < mid_num,val 在data_list左半部分
所以最大下标high=mid-1==2,左半部分列表==[1, 3, 5]
mid=(low+high)//2==1
中间数mid_num=data_list[1]==3
val == mid_num
查找完成
bisect--数组二分查找算法
bisect 模块包含两个主要函数( bisect 和 insort),它们内部利用二分查找算法,分别用于在有序序列中查找元素与插入元素。
- 查找: bisect(array, item)
- 插入: insort(array,item)
bisect有三个方法
- bisect.bisect()
- bisect.bisect_left()
- bisect.bisect_right()
- 貌似bisect()与bisect_right()作用相同
语法:bisect.bisect_left(a,x, lo=0, hi=len(a))
说明:a=序列变量,x=查找的值,lo=检索的起始位置,hi=检索的结束位置 lo、hi可以忽略,忽略后使用整个列表
bisect.bisect_left函数返回这样的位置:位置左侧值都小于x, 位置右侧大于等于
bisect.bisect_right函数返回这样的位置:位置左侧值都小于等于x, 位置右侧大于
bisect_left与bisect_right 并不添加至序列 只是返回应该排序的位置
当没有相同元素时,三个方法返回值相等
tuple_1 = (1, 3, 5, 7, 9) print(bisect.bisect(tuple_1, 4))
print(bisect.bisect_left(tuple_1, 4)) print(bisect.bisect_right(tuple_1, 4))
#输出 2 2 2
当有相同元素时:
tuple_1 = (1, 3, 5, 5, 7, 9) print(bisect.bisect(tuple_1, 5))
print(bisect.bisect_left(tuple_1, 5)) print(bisect.bisect_right(tuple_1, 5))
#输出 4 2 4
对比查询效率
输出:
#输出
a1:33554433
二分查找bisect:25.99148979s
a2:33554432
常规list.index:32.69605091s
insort和bisect一样对应三个方法
- bisect.insort()
- bisect.insort_left()
- bisect.insort_right()
当插入不存在的元素时,三个方法作用相同
当插入存在的元素时,判断插入该元素的前面(insort, insort_left)还是后面(insort_right)