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回文字符串及回文数字判定功能示例
Mar 20 Python
Python numpy 提取矩阵的某一行或某一列的实例
Apr 03 Python
详解Django之auth模块(用户认证)
Apr 17 Python
python基于物品协同过滤算法实现代码
May 31 Python
Django框架模板语言实例小结【变量,标签,过滤器,继承,html转义】
May 23 Python
python 三元运算符使用解析
Sep 16 Python
Keras:Unet网络实现多类语义分割方式
Jun 11 Python
Python自动化xpath实现自动抢票抢货
Sep 19 Python
PyQt5 显示超清高分辨率图片的方法
Apr 11 Python
使用numpy nonzero 找出非0元素
May 14 Python
pandas求平均数和中位数的方法实例
Aug 04 Python
JAVA SpringMVC实现自定义拦截器
Mar 16 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中删除、清空session的方式总结
2015/10/09 PHP
PHP中静态变量的使用方法实例分析
2016/12/01 PHP
深入理解PHP的远程多会话调试
2017/09/21 PHP
实现JavaScript中继承的三种方式
2009/10/16 Javascript
基于jquery的一个图片hover的插件
2010/04/24 Javascript
Node调试工具JSHint的安装及配置教程
2014/05/27 Javascript
一个简单的jQuery插件ajaxfileupload.js实现ajax上传文件例子
2014/06/26 Javascript
js动态创建及移除div的方法
2015/06/03 Javascript
Javascript中的几种继承方式对比分析
2016/03/22 Javascript
js实现商品抛物线加入购物车特效
2020/11/18 Javascript
基于js对象,操作属性、方法详解
2016/08/11 Javascript
KnockoutJS 3.X API 第四章之click绑定
2016/10/10 Javascript
JS中动态创建元素的三种方法总结(推荐)
2016/10/20 Javascript
vue.js学习之递归组件
2016/12/13 Javascript
JavaScript fetch接口案例解析
2018/08/30 Javascript
Vue事件修饰符native、self示例详解
2019/07/09 Javascript
vue实现整屏滚动切换
2020/06/29 Javascript
vue修改Element的el-table样式的4种方法
2020/09/17 Javascript
[42:32]VP vs RNG 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.21.mp4
2020/07/19 DOTA
Python判断文件和文件夹是否存在的方法
2015/05/21 Python
python实现读取命令行参数的方法
2015/05/22 Python
python中map()与zip()操作方法
2016/02/27 Python
解决Python3中的中文字符编码的问题
2018/07/18 Python
windows上安装python3教程以及环境变量配置详解
2019/07/18 Python
PyInstaller运行原理及常用操作详解
2020/06/13 Python
深入了解Python 方法之类方法 &amp; 静态方法
2020/08/17 Python
让ie浏览器成为支持html5的浏览器的解决方法(使用html5shiv)
2014/04/08 HTML / CSS
如何在Canvas上的图形/图像绑定事件监听的实现
2020/09/16 HTML / CSS
企业为何需要商业计划书
2013/12/26 职场文书
中学家长会邀请函
2014/01/17 职场文书
教师节促销活动方案
2014/02/14 职场文书
家长会欢迎词
2015/01/23 职场文书
个人年终总结开头
2015/03/06 职场文书
会议主持词结束语
2015/07/03 职场文书
MySql重置root密码 --skip-grant-tables
2022/04/11 MySQL
Ubuntu Server 安装Tomcat并配置systemctl
2022/04/28 Servers