Python 二分查找与 bisect 模块
admin
2023-07-31 00:47:26
0

Python 的列表(list)内部实现是一个数组,也就是一个线性表。在列表中查找元素可以使用 list.index() 方法,其时间复杂度为O(n)。对于大数据量,则可以用二分查找进行优化。二分查找要求对象必须有序,其基本原理如下:

  • 1.从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;
  • 2.如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。
  • 3.如果在某一步骤数组为空,则代表找不到。

二分查找也成为折半查找,算法每一次比较都使搜索范围缩小一半, 其时间复杂度为 O(logn)。

我们分别用递归和循环来实现二分查找:

12345678910111213141516171819202122 def binary_search_recursion(lst, value, low, high):      if high < low:          return None    mid = (low + high) / 2      if lst[mid] > value:          return binary_search_recursion(lst, value, low, mid1)      elif lst[mid] < value:          return binary_search_recursion(lst, value, mid+1, high)      else:          return mid   def binary_search_loop(lst,value):      low, high = 0, len(lst)1      while low <= high:          mid = (low + high) / 2          if lst[mid] < value:              low = mid + 1          elif lst[mid] > value:              high = mid 1        else:            return mid      return None

接着对这两种实现进行一下性能测试:

1234567891011121314151617 if __name__ == \”__main__\”:    import random    lst = [random.randint(0, 10000) for _ in xrange(100000)]    lst.sort()     def test_recursion():        binary_search_recursion(lst, 999, 0, len(lst)1)     def test_loop():        binary_search_loop(lst, 999)     import timeit    t1 = timeit.Timer(\”test_recursion()\”, setup=\”from __main__ import test_recursion\”)    t2 = timeit.Timer(\”test_loop()\”, setup=\”from __main__ import test_loop\”)     print \”Recursion:\”, t1.timeit()    print \”Loop:\”, t2.timeit()

执行结果如下:

12 Recursion: 3.12596702576Loop: 2.08254289627

可以看出循环方式比递归效率高。

Python 有一个 bisect 模块,用于维护有序列表。bisect 模块实现了一个算法用于插入元素到有序列表。在一些情况下,这比反复排序列表或构造一个大的列表再排序的效率更高。Bisect 是二分法的意思,这里使用二分法来排序,它会将一个元素插入到一个有序列表的合适位置,这使得不需要每次调用 sort 的方式维护有序列表。

下面是一个简单的使用示例:

1234567891011121314 import bisectimport random random.seed(l>

  • 1.从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;
  • 2.如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。
  • 3.如果在某一步骤数组为空,则代表找不到。
  • 二分查找也成为折半查找,算法每一次比较都使搜索范围缩小一半, 其时间复杂度为 O(logn)。

    我们分别用递归和循环来实现二分查找:

    12345678910111213141516171819202122 def binary_search_recursion(lst, value, low, high):      if high < low:          return None    mid = (low + high) / 2      if lst[mid] > value:          return binary_search_recursion(lst, value, low, mid1)      elif lst[mid] < value:          return binary_search_recursion(lst, value, mid+1, high)      else:          return mid   def binary_search_loop(lst,value):      low, high = 0, len(lst)1      while low <= high:          mid = (low + high) / 2          if lst[mid] < value:              low = mid + 1          elif lst[mid] > value:              high = mid 1        else:            return mid      return None

    接着对这两种实现进行一下性能测试:

    1234567891011121314151617 if __name__ == \”__main__\”:    import random    lst = [random.randint(0, 10000) for _ in xrange(100000)]    lst.sort()     def test_recursion():        binary_search_recursion(lst, 999, 0, len(lst)1)     def test_loop():        binary_search_loop(lst, 999)     import timeit    t1 = timeit.Timer(\”test_recursion()\”, setup=\”from __main__ import test_recursion\”)    t2 = timeit.Timer(\”test_loop()\”, setup=\”from __main__ import test_loop\”)     print \”Recursion:\”, t1.timeit()    print \”Loop:\”, t2.timeit()

    执行结果如下:

    12 Recursion: 3.12596702576Loop: 2.08254289627

    可以看出循环方式比递归效率高。

    Python 有一个 bisect 模块,用于维护有序列表。bisect 模块实现了一个算法用于插入元素到有序列表。在一些情况下,这比反复排序列表或构造一个大的列表再排序的效率更高。Bisect 是二分法的意思,这里使用二分法来排序,它会将一个元素插入到一个有序列表的合适位置,这使得不需要每次调用 sort 的方式维护有序列表。

    下面是一个简单的使用示例:

    1234567891011121314 import bisectimport random 

    相关内容

    热门资讯

    500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
    定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
    65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
    Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
    scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
    pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
    小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
    Prometheus+Graf... 一,Prometheus概述 1,什么是Prometheus?Prometheus是最初在Sound...
    python绘图库Matplo... 本文简单介绍了Python绘图库Matplotlib的安装,简介如下: matplotlib是pyt...
    微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...