最简单的方法实现 Python数组二分查找算法
bisect 数组二分查找算法
不想自己手写二分查找?
可以,一个 import bisect
帮你完成开包即用的 Binary Search。
bisect 是一个python标准库,直接导入就可以使用。
方法1: bisect.bisect_left()
bisect.bisect_left(a, x, lo=0, hi=len(a))
参数说明:
-
a:表示插入的数组 -
x:即将插入到数组中的一个数值类型的元素
返回值:元素x插入到数组a后在数组中的位置索引(不执行插入操作,只计算索引,数组a保持不变),如果x在a中已经存在,则x插入到已存在元素的左侧。
例子:
可以看到,元素8在插入到数组a后的位置索引为 3,新插入的元素x(8)在已经存在数组a中的元素8的左侧。
方法2: bisect.bisect_right()
bisect.bisect_right(a, x, lo=0, hi=len(a))
参数说明:
-
a:表示插入的数组 -
x:即将插入到数组中的一个数值类型的元素
返回值:元素x插入到数组a后在数组中的位置索引(不执行插入操作,只计算索引,数组a保持不变),如果x在a中已经存在,则x插入到已存在元素的右侧。
例子:
可以看到,元素8在插入到数组a后的位置索引为 4,新插入的元素x(8)在已经存在数组a中的元素8的右侧。
方法3: bisect.bisect()
bisect.bisect(a, x, lo=0, hi=len(a))
效果同 bisect_right,可以看作是 bisect_right 的缩写。
方法4: bisect.insort_left()
bisect.insort_left(a, x, lo=0, hi=len(a))
同 bisect_left 原理一致,只不过 bisect_left 不真正执行插入操作,而 insort_left 执行插入操作,数组a发生改变。
相当于
a.insert(bisect.bisect_left(a, x, lo, hi), x)
例子:
这里红圈的 8 就是插入的参数 x。
方法5: bisect.insort_right()
bisect.insort_right(a, x, lo=0, hi=len(a))
同 bisect_right 原理一致,只不过 bisect_right 不真正执行插入操作,而 insort_right 执行插入操作,数组a发生改变。
相当于
a.insert(bisect.bisect_right(a, x, lo, hi), x)
例子:
这里红圈的 8 就是插入的参数 x,注意和 insort_left 的区别。
方法6: bisect.insort()
bisect.insort(a, x, lo=0, hi=len(a))
效果同 insort_right,可以看作是 insort_right 的缩写。
应用
查询 x 是否在数组 a 中, 如果在返回位置索引
a=[1, 5, 7, 8, 9]
def index(a, x):
i = bisect.bisect_left(a, x)
if i != len(a) and a[i] == x:
return i
raise ValueError
注意:如果有重复值,返回最左侧位置的索引
类似数据分组
函数 bisect() 还可以用于数字表查询。这个例子是使用 bisect() 从一个给定的考试成绩集合里,通过一个有序数字表,查出其对应的字母等级:90 分及以上是 'A',80 到 89 是 'B',以此类推。
def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
i = bisect.bisect(breakpoints, score)
return grades[i]
[grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]