代码改变世界

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

类似的,不多做描述。