Python中实现二分查找和插入的bisect模块的用法

根据官方文档,bisect中的方法包括:

bisect.bisect_left(a,x,lo=0,hi=len(a),*,key=None),在有序数组a中[lo,hi]区间内查找x插入的位置,返回的是索引值。如果a中有跟x相同的元素,则x插入的位置是左边(不理解可以看下方的例子),key指定了一个单参数的方法,该方法的返回值作为与k比较的基准(不理解看下方例子)。

值得注意的是,key参数是3.10版本以后才添加的功能。

bisect.bisect_right(a,x,lo=0,hi=len(a),*,key=None),在有序数组a中[lo,hi]区间内查找x插入的位置,返回索引值。如果a中有跟x相同的元素,则x插入的位置是右边。

bisect.bisect(a,x,lo=0,hi=len(a),*,key=None),同bisect_right

# bisect_left Vs. bisect (bisect_right)
import
bisect nums=[1,2,2,4] i,j=bisect.bisect_left(nums,2),bisect.bisect(nums,2) print(i) # 输出1 print(j) # 输出3

可见,针对上面给出的数组,想要插入2,使用bisect_left返回的索引值是1,使用bisect(bisect_right)返回的索引值是3。如果指定了lo和hi的话,那么返回的就是在这个范围内的索引。如下面的例子所示。

# 指定lo和hi
import
bisect nums=[1,2,2,2,2,4] i=bisect.bisect_left(nums,2,3) print(i) # 输出为3

如果不指定lo=3的话,返回的索引应该是1。指定lo=3后,返回的索引为3。

关键字key指定了一个方法,这个方法会接受当前数组中的中间值mid(因为二分查找就是从中间值开始的)作为其参数,然后返回一个值val,val用于跟x比较。

复制代码
# key
import bisect
nums=[1,2,3,4,6,8]
def divide(mid):
    print('mid: '+str(mid))
    return mid//2

i=bisect.bisect_left(nums,5,key=divide)
print(i)
复制代码

上面的例子中定义了一个divide方法。那么bisect_left方法的执行顺序是这样的:

1.nums中的中间值mid=4, divide(mid)方法返回值为2

2.5>2,则查找nums的右子数组,即[6,8]

3.[6,8]的中间值是mid=8, divide(mid)方法返回值为4

4.5>4,则继续查找右子数组,可是已经没有右子数组了,则返回索引值为6.

上面代码的输出为:

bisect.insort_left(a,x,lo=0,hi=len(a),*,key=None),在有序数组a中插入x,相同的值则插在最左边。

bisect.insort_right(a,x,lo=0,hi=len(a),*,key=None),在有序数组a中插入x,相同的值则插在最右边。

bisect.insort(a,x,lo=0,hi=len(a),*,key=None),同上。

# bisect.insort_left 
import bisect
nums=[1,2,3,4,6,8]
bisect.insort_left(nums,5)
print(nums)

输出:[1,2,3,4,5,6,8]

值得注意的是,insort方法中的key和bisect方法中的key指定的方法针对的对象是不同的。看相同的例子:

复制代码
# bisect.insort_left with key
import bisect
nums=[1,2,3,4,6,8]

def divide(mid):
    print('mid: '+str(mid))
    return mid//2

bisect.insort_left(nums,5,key=divide)
复制代码

输出是这样的:

可见,key指定的方法的参数是针对x的。也就是说insort_left方法的执行顺序是这样的:

1.mid=x=5,返回的值是2,也就是divide(x)

2.mid是数组的中间值,即mid=4, divide方法返回的值是2

3.divide(x)==2,则查找左子数组

4.中间值为2,mid=2, divide方法返回的值是1

5.divide(x)>1,则查找右子数组

6.中间值为3,mid=3, divide方法的返回值是1

7.divide(x)>1,则查找右子数组

8.没有右子数组了,则插入位置的索引为3

得到了插入5之后的数组为[1,2,3,5,4,6,8]

posted @   南风小斯  阅读(1026)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示