Python bisect库的用法:用于有序序列的插入和非逆序系列的二分查找

1. bisect 使用要点

bisect 的意思是 “平分,二等分”

bisect 是 python 的内置库,有两个模块:

  • bisect.bisect 二分查找模块,包括 bisect.bisect(), bisect.bisect_left() 和 bisect.bisect_right() 三个函数,返回值为查找元素的下标
    bisect.bisect 可以用于非逆序系列的二分查找,即递增列表和乱序列表都可以使用

  • bisect.insort 插入模块, 包括 bisect.insort(), bisect.insort_left() 和 bisect.insort_right() 三个函数,返回值插入新元素后的列表
    bisect.insort 只能在递增列表中插入新元素,即不能用于乱序和逆向列表

总结一下就是, bisect 库用于有序序列的插入和非逆序系列的二分查找

2. bisect.bisect 二分查找模块

本节参考博客 Python中的bisect库(二分查找库)用法

bisect.bisect 模块包括三个函数,返回值为查找元素的下标:

  • bisect.bisect(list, target)
  • bisect.bisect_left (list, target)
  • bisect.bisect_right(list, target)

我们在数组中进行查找目标值 target 时,会出现三种情况:

  1. target 不在数组中
  2. target 在数组中且只有一个
  3. target 在数组中并且有多个

下面分别进行分析

2.1 target 不在数组中

import bisect

array = [1, 2, 3, 4, 7, 9, 9, 9, 9, 10]     # len(array)=10
a = bisect.bisect(array, 6)           # a=4
b = bisect.bisect_left(array, 6)      # b=4
c = bisect.bisect_right(array, 6)     # c=4
print(a, b, c)

此时三个函数的输出值都是一样的,输出的值都是在合适的插入点索引,使得数组有序。

2.2 target 在数组中且只有一个

import bisect

array = [1, 2, 3, 4, 7, 9, 9, 9, 9, 10]     # len(array)=10
a = bisect.bisect(array, 7)           # a=5
b = bisect.bisect_left(array, 7)      # b=4
c = bisect.bisect_right(array, 7)     # c=5
print(a, b, c)

bisect_left() 函数的输出是 target 在 list 中的数组下标,其余两个函数的输出下标+1

bisect_left() 的输出是符合用户直觉感受的,另外两个函数不符

2.3 target 在数组中并且有多个

import bisect

array = [1, 2, 3, 4, 7, 9, 9, 9, 9, 10]     # len(array)=10
a = bisect.bisect(array, 9)           # a=9
b = bisect.bisect_left(array, 9)      # b=5
c = bisect.bisect_right(array, 9)     # c=9
print(a, b, c)

bisect_left() 函数的输出是 target 在 list 中最左面值的数组下标,其余两个函数的输出为最右面的数组下标 +1

bisect_left() 的输出是符合用户直觉感受的,另外两个函数不符

2.4 使用总结:只用 bisect_left()

不管什么情况,就用 bisect.bisect_left()

再次总结一下 bisect.bisect_left() 的用法:

import bisect

array = [1, 2, 3, 4, 7, 9, 9, 9, 9, 10]     # len(array)=10
a = bisect.bisect_left(array, 6)      # a=4
b = bisect.bisect_left(array, 7)      # b=4
c = bisect.bisect_left(array, 9)      # c=5
print(a, b, c)

乱序列表的元素查找见 2.5 小节

2.5 bisect 不能用于倒序列表

bisect 可以在非递减和逆序列表中查找元素,但不能用于倒序列表。以 bisect.bisect_left() 为例:

(1)乱序列表可以使用

import bisect

# 乱序列表
array = [1, 4, 2, 3, 7, 9, 9, 10, 9, 1]       # len(array)=10
a = bisect.bisect_left(array, 6)      # a=4   target不在数组中
b = bisect.bisect_left(array, 7)      # b=4   target在数组中且只有一个
c = bisect.bisect_left(array, 9)      # c=5   target在数组中并且有多个
print(a, b, c)

可以看到,在乱序列表中,bisect_left() 依然返回了 target 第一次出现的下标位置

(2)逆序列表不可以使用

import bisect

# 逆序列表
array = [10, 9, 9, 9, 8, 7, 6, 5, 3, 2]     # len(array)=10
a = bisect.bisect_left(array, 6)      # a=0   target不在数组中
b = bisect.bisect_left(array, 7)      # b=0   target在数组中且只有一个
c = bisect.bisect_left(array, 9)      # c=10  target在数组中并且有多个
print(a, b, c)

可以看到,在逆序列表中查找元素时,bisect_left() 的返回值是错误的

3. bisect.insort 元素插入模块

3.1 函数功能

bisect.insort 模块用于将新元素插入非递减列表,得到的新列表依然是非递减的。且在原始列表有序的情况下, insort(), insort() 和 insort_right() 三个函数的作用是相同的,见代码示例:

import bisect

array = [1, 2, 4, 5, 6]

bisect.insort(array, 2)
print(array)     # [1, 2, 2, 4, 5, 6]

bisect.insort_left(array, 3)
print(array)     # [1, 2, 2, 3, 4, 5, 6]

bisect.insort_right(array, 7)
print(array)     # [1, 2, 2, 3, 4, 5, 6, 7]

3.2 insort 不能用于倒序和乱序列表

insort 模块只能用于非递减的有序列表,不能用于倒序和乱序列表:

(1)逆序列表不可以使用

bisect.insort():

import bisect

array = [6, 5, 4, 2, 1]

bisect.insort(array, 0)
print(array)     # [0, 6, 5, 4, 2, 1]

bisect.insort(array, 3)
print(array)     # [0, 3, 6, 5, 4, 2, 1]

bisect.insort(array, 5)
print(array)     # [0, 3, 6, 5, 4, 2, 1, 5]

bisect.insort_left():

import bisect

array = [6, 5, 4, 2, 1]

bisect.insort_left(array, 0)
print(array)     # [0, 6, 5, 4, 2, 1]

bisect.insort_left(array, 3)
print(array)     # [0, 3, 6, 5, 4, 2, 1]

bisect.insort_left(array, 5)
print(array)     # [0, 3, 5, 6, 5, 4, 2, 1]

bisect.insort_right():

import bisect

array = [6, 5, 4, 2, 1]

bisect.insort_right(array, 0)
print(array)     # [0, 6, 5, 4, 2, 1]

bisect.insort_right(array, 3)
print(array)     # [0, 3, 6, 5, 4, 2, 1]

bisect.insort_right(array, 5)
print(array)     # [0, 3, 6, 5, 4, 2, 1, 5]

(2)乱序列表不可以使用

给乱序列表中插入元素本来就是没有太大意义的,此处代码验证省略。

猜你喜欢

转载自blog.csdn.net/qq_43799400/article/details/131624791
今日推荐