python的算法:二分法查找(2)--bisect模块
2017-07-04 09:25 很大很老实 阅读(467) 评论(0) 编辑 收藏 举报Python 有一个 bisect
模块,用于维护有序列表。bisect
模块实现了一个算法用于插入元素到有序列表。在一些情况下,这比反复排序列表或构造一个大的列表再排序的效率更高。Bisect 是二分法的意思,这里使用二分法来排序,它会将一个元素插入到一个有序列表的合适位置,这使得不需要每次调用 sort 的方式维护有序列表。
先看一个最简单的用法:
import bisect l=[1,3,3,6,8,12,15] x=4 left_insert_point=bisect.bisect_left(l,x) right_insert_point=bisect.bisect_right(l,x) print(left_insert_point) print(right_insert_point)
两个的结果,都是3
import bisect l=[1,3,3,6,8,12,15] x=3 left_insert_point=bisect.bisect_left(l,x) right_insert_point=bisect.bisect_right(l,x) print(left_insert_point) print(right_insert_point)
结果分别是1,3
bisect的模块不复杂,现在,我们先看bisect_left这个函数:
def bisect_left(a, x, lo=0, hi=None): """Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e < x, and all e in a[i:] have e >= x. So if x already appears in the list, a.insert(x) will insert just before the leftmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. """ if lo < 0: raise ValueError('lo must be non-negative') if hi is None: hi = len(a) while lo < hi: mid = (lo+hi)//2 if a[mid] < x: lo = mid+1 else: hi = mid return lo
这里,假定的,就是,a是一个有序的数组。
假设,我们有这么一个数组:
p=[1,4,3,3,6,8,12,15,0,9,3,28]
这实际上,p不是有序的e。
根据bisect_left的算法,每次都是二分。如果查找4的插入位置,当找到3的时候,就停止找了。所以,返回是4.
再看bisect_right:
def bisect_right(a, x, lo=0, hi=None): """Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e <= x, and all e in a[i:] have e > x. So if x already appears in the list, a.insert(x) will insert just after the rightmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. """ if lo < 0: raise ValueError('lo must be non-negative') if hi is None: hi = len(a) while lo < hi: mid = (lo+hi)//2 if x < a[mid]: hi = mid else: lo = mid+1 return lo
类似的,不多做描述。