Python bisect 库详细介绍
Python bisect 库详细介绍
bisect
是 Python 标准库中的一个模块,提供了基于二分查找算法的工具,用于维护有序列表而不必每次插入后都重新排序。
核心功能
bisect
模块主要用于以下场景:
- 在有序列表中快速查找元素位置
- 将元素插入到有序列表的正确位置,保持列表有序
主要函数
查找函数
- bisect_left(a, x, lo=0, hi=len(a))
- 在有序列表
a
中查找x
的插入位置 - 返回的位置使得
x
插入后,所有位于该位置左边的元素都 小于x
- 如果
x
已存在,则返回最左边的位置
- 在有序列表
- bisect_right(a, x, lo=0, hi=len(a)) (或简写为
bisect
)- 类似
bisect_left
,但当x
存在时返回最右边的位置+1
- 类似
插入函数
- insort_left(a, x, lo=0, hi=len(a))
- 将
x
插入到有序列表a
中,保持顺序 - 当
x
存在时,插入到最左边
- 将
- insort_right(a, x, lo=0, hi=len(a)) (或简写为
insort
)- 类似
insort_left
,但当x
存在时插入到最右边
- 类似
使用示例
基本查找
import bisectdata = [1, 3, 5, 7, 9]# 查找不存在的元素
print(bisect.bisect_left(data, 4)) # 输出: 2
print(bisect.bisect_right(data, 4)) # 输出: 2# 查找存在的元素
print(bisect.bisect_left(data, 5)) # 输出: 2
print(bisect.bisect_right(data, 5)) # 输出: 3
元素插入
import bisectdata = [1, 3, 5, 7, 9]bisect.insort_left(data, 4)
print(data) # 输出: [1, 3, 4, 5, 7, 9]bisect.insort_right(data, 5)
print(data) # 输出: [1, 3, 4, 5, 5, 7, 9]
实际应用案例
案例1:成绩转换
import bisectdef grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):i = bisect.bisect(breakpoints, score)return grades[i]print(grade(65)) # D
print(grade(85)) # B
print(grade(95)) # A
案例2:区间查找
import bisectdef find_range(value, ranges):# ranges 应该是一个已排序的区间起点列表pos = bisect.bisect_right(ranges, value) - 1return pos if pos >= 0 else Noneranges = [0, 10, 20, 30, 40]
print(find_range(15, ranges)) # 输出: 1 (在10-20区间)
高级用法
处理自定义对象
import bisectclass Student:def __init__(self, name, score):self.name = nameself.score = scoredef __lt__(self, other):return self.score < other.scorestudents = [Student('Alice', 85),Student('Bob', 75),Student('Charlie', 90)
]
students.sort() # 按分数排序# 查找插入位置
new_student = Student('David', 80)
pos = bisect.bisect_left(students, new_student)
students.insert(pos, new_student)for s in students:print(f"{s.name}: {s.score}")
使用 key 函数(Python 3.10+)
import bisectdata = [{'score': 65}, {'score': 75}, {'score': 85}]# 查找 score=80 应该插入的位置
pos = bisect.bisect_left(data, 80, key=lambda x: x['score'])
print(pos) # 输出: 2
性能特点
- 查找效率:O(log n) 时间复杂度,比线性查找 O(n) 高效
- 插入效率:O(n) 时间复杂度,因为需要移动元素
- 适用场景:
- 列表基本有序,偶尔需要插入新元素
- 需要频繁查找但相对较少插入的情况
注意事项
- 输入列表 必须是有序的,否则结果不可靠
- 对于自定义对象,需要确保实现了
__lt__()
方法 - Python 3.10+ 支持
key
参数,类似list.sort()
的key
参数
bisect
模块是处理有序数据的利器,特别适合那些需要保持数据有序同时又需要高效查找的场景。