Python中bisect的使用方法

作者:北洛 时间:2021-12-03 05:56:12 

Python中列表(list)的实现其实是一个数组,当要查找某一个元素的时候时间复杂度是O(n),使用list.index()方法,但是随着数据量的上升,list.index()的性能也逐步下降,所以我们需要使用bisect模块来进行二分查找,前提我们的列表是一个有序的列表。

递归二分查找和循环二分查找


def binary_search_recursion(lst, val, start, end):
 if start > end:
   return None
 mid = (start + end) // 2
 if lst[mid] < val:
   return binary_search_recursion(lst, val, mid + 1, end)
 if lst[mid] > val:
   return binary_search_recursion(lst, val, start, mid - 1)
 return mid

def binary_search_loop(lst, val):
 start, end = 0, len(lst) - 1
 while start <= end:
   mid = (start + end) // 2
   if lst[mid] < val:
     start = mid + 1
   elif lst[mid] > val:
     end = mid - 1
   else:
     return mid
 return None

为了比对一下两者的性能,我们使用timeit模块来测试两个方法执行,timeit模块的timeit方法默认会对需要测试的函数执行1000000,然后返回执行的时间。


>>> import random
>>> from random import randint
>>> from random import choice
>>> random.seed(5)
>>> lst = [randint(1, 100) for _ in range(500000)]
>>> lst.sort()
>>> val = choice(lst)
>>> val
6
>>> def test_recursion():
...   return binary_search_recursion(lst, val, 0, len(lst) - 1)
...
>>> def test_loop():
...   return binary_search_loop(lst, val)
...
>>> import timeit
>>> t1 = timeit.timeit("test_recursion()", setup="from __main__ import test_recursion")
>>> t1
3.9838006450511045
>>> t2 = timeit.timeit("test_loop()", setup="from __main__ import test_loop")
>>> t2
2.749765167240339

可以看到,循环二分查找比递归二分查找性能要来的好些。现在,我们先用bisect的二分查找测试一下性能

用bisect来搜索


>>> import bisect
>>> def binary_search_bisect(lst, val):
...   i = bisect.bisect(lst, val)
...   if i != len(lst) and lst[i] == val:
...     return i
...   return None
...
>>> def test_bisect():
...   return binary_search_bisect(lst, val)
...
>>> t3 = timeit.timeit("test_bisect()", setup="from __main__ import test_bisect")
>>> t3
1.3453236258177412

对比之前,我们可以看到用bisect模块的二分查找的性能比循环二分查找快一倍。再来对比一下,如果用Python原生的list.index()的性能


>>> def test_index():
...   return lst.index(val)
...
>>> t4 = timeit.timeit("test_index()", setup="from __main__ import test_index")
>>> t4
518.1656223725007

可以看到,如果用Python原生的list.index()执行1000000,需要500秒,相比之前的二分查找,性能简直慢到恐怖

用bisect.insort插入新元素

排序很耗时,因此在得到一个有序序列之后,我们最好能够保持它的有序。bisect.insort就是为这个而存在的

insort(seq, item)把变量item插入到序列seq中,并能保持seq的升序顺序


import random
from random import randint
import bisect

lst = []
SIZE = 10
random.seed(5)
for _ in range(SIZE):
 item = randint(1, SIZE)
 bisect.insort(lst, item)
 print('%2d ->' % item, lst)

输出:

10 -> [10]
 5 -> [5, 10]
 6 -> [5, 6, 10]
 9 -> [5, 6, 9, 10]
 1 -> [1, 5, 6, 9, 10]
 8 -> [1, 5, 6, 8, 9, 10]
 4 -> [1, 4, 5, 6, 8, 9, 10]
 1 -> [1, 1, 4, 5, 6, 8, 9, 10]
 3 -> [1, 1, 3, 4, 5, 6, 8, 9, 10]
 2 -> [1, 1, 2, 3, 4, 5, 6, 8, 9, 10]

来源:https://www.cnblogs.com/beiluowuzheng/p/8452671.html

标签:Python,bisect,使用
0
投稿

猜你喜欢

  • 详解如何通过Python制作一个密码生成器

    2023-11-24 10:36:43
  • 详解Python核心编程中的浅拷贝与深拷贝

    2021-05-04 15:44:09
  • python实现彩色图转换成灰度图

    2022-03-11 02:41:30
  • python爬虫开发之selenium模块详细使用方法与实例全解

    2022-12-15 01:28:40
  • Python time时间格式化和设置时区实现代码详解

    2023-05-17 00:09:17
  • 使用JScript遍历Request表单参数集合

    2011-02-26 11:08:00
  • SQL Server 使用 SET FMTONLY ON 获得表的元数据

    2024-01-24 00:20:41
  • Python爬虫实现模拟点击动态页面

    2022-05-19 05:21:19
  • python数字类型math库原理解析

    2021-11-27 16:34:50
  • Python线性回归实战分析

    2023-05-19 04:35:42
  • SQL SERVER 日志已满的处理方法

    2010-07-31 13:32:00
  • MySQL数据库事务transaction示例讲解教程

    2024-01-27 06:43:04
  • Django2.1.3 中间件使用详解

    2023-11-06 19:46:00
  • Python 3.7新功能之dataclass装饰器详解

    2023-09-13 16:32:38
  • Python之日期与时间处理模块(date和datetime)

    2023-09-29 12:53:06
  • 使用Python制作新型冠状病毒实时疫情图

    2023-03-01 20:17:19
  • vue-swiper的使用教程

    2024-04-27 16:17:56
  • 浅谈python中的面向对象和类的基本语法

    2023-06-27 11:36:45
  • adonet基础示例分享(adonet连接数据库)

    2024-01-15 23:15:44
  • 对python3标准库httpclient的使用详解

    2021-09-07 06:48:02
  • asp之家 网络编程 m.aspxhome.com