Python中bisect的使用方法


Posted in Python onDecember 31, 2019

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]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python采集博客中上传的QQ截图文件
Jul 18 Python
Python 正则表达式(转义问题)
Dec 15 Python
Python使用正则表达式抓取网页图片的方法示例
Apr 21 Python
详解python 字符串和日期之间转换 StringAndDate
May 04 Python
django上传图片并生成缩略图方法示例
Dec 11 Python
Django REST为文件属性输出完整URL的方法
Dec 18 Python
python自动发邮件库yagmail的示例代码
Feb 23 Python
浅谈django三种缓存模式的使用及注意点
Sep 30 Python
python实现计数排序与桶排序实例代码
Mar 28 Python
python并发爬虫实用工具tomorrow实用解析
Sep 25 Python
Python Selenium截图功能实现代码
Apr 26 Python
Python新手学习raise用法
Jun 03 Python
pytorch中tensor张量数据类型的转化方式
Dec 31 #Python
Pytorch之parameters的使用
Dec 31 #Python
使用TensorFlow-Slim进行图像分类的实现
Dec 31 #Python
Pytorch之view及view_as使用详解
Dec 31 #Python
window环境pip切换国内源(pip安装异常缓慢的问题)
Dec 31 #Python
如何基于Python创建目录文件夹
Dec 31 #Python
Pytorch之contiguous的用法
Dec 31 #Python
You might like
为PHP初学者的8点有效建议
2010/11/20 PHP
PHP通过内置函数memory_get_usage()获取内存使用情况
2014/11/20 PHP
PHP + plupload.js实现多图上传并显示进度条加删除实例代码
2017/03/06 PHP
基于php流程控制语句和循环控制语句(讲解)
2017/10/23 PHP
PHP的mysqli_set_charset()函数讲解
2019/01/23 PHP
JavaScript提高网站性能优化的建议(二)
2016/07/24 Javascript
jquery实现界面无刷新加载登陆注册
2016/07/30 Javascript
jQuery实现复制到粘贴板功能
2017/02/11 Javascript
Java中int与integer的区别(基本数据类型与引用数据类型)
2017/02/19 Javascript
jQuery复合事件结合toggle()方法的用法示例
2017/06/10 jQuery
JS实现的走迷宫小游戏完整实例
2017/07/19 Javascript
Node.js 基础教程之全局对象
2017/08/06 Javascript
layer弹出层 iframe层去掉滚动条的实例代码
2018/08/17 Javascript
vue通过style或者class改变样式的实例代码
2018/10/30 Javascript
BootStrap中的模态框(modal,弹出层)功能示例代码
2018/11/02 Javascript
Vue父子之间值传递的实例教程
2020/07/02 Javascript
使用Element的InfiniteScroll 无限滚动组件报错的解决
2020/07/27 Javascript
Python 3中的yield from语法详解
2017/01/18 Python
Python使用time模块实现指定时间触发器示例
2017/05/18 Python
Python+request+unittest实现接口测试框架集成实例
2018/03/16 Python
python 日志增量抓取实现方法
2018/04/28 Python
深入分析python中整型不会溢出问题
2018/06/18 Python
Python中函数的返回值示例浅析
2019/08/28 Python
基于Python中的yield表达式介绍
2019/11/19 Python
virtualenv介绍及简明教程
2020/06/23 Python
python中pathlib模块的基本用法与总结
2020/08/17 Python
Belvilla法国:休闲度假房屋出租
2020/10/03 全球购物
Linux Interview Questions For software testers
2012/06/02 面试题
应用艺术专业个人的自我评价
2014/01/03 职场文书
幼儿园庆六一活动方案
2014/03/06 职场文书
社区居务公开实施方案
2014/03/27 职场文书
信访工作汇报材料
2014/10/27 职场文书
银行文明优质服务培训心得体会
2016/01/09 职场文书
如何使用flask将模型部署为服务
2021/05/13 Python
windows安装python超详细图文教程
2021/05/21 Python
深入理解 Golang 的字符串
2022/05/04 Golang