Python中bisect的使用方法

2022-08-22 00:33:10 字數 3243 閱讀 2529

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

可以看到,迴圈二分查詢比遞迴二分查詢效能要來的好些。現在,我們先用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中bisect的使用

1 2 這裡,就我有疑問的地方做個記錄 第一,bisect模組中的函式都有哪些用途。根據python 的參考手冊,這個模組的主要用途是運用bisection algorithm 分半演算法 在已序的列表中進行查詢和插入操作。練習中使用了bisect left a,x 函式,這個函式給出了x元素在列表...

Python中bisect的用法

一般來說,python中的bisect用於操作排序的陣列,比如你可以在向乙個陣列插入資料的同時進行排序。下面的 演示了如何進行操作 import bisect import random random.seed 1 print new pos contents print l for i in ra...

Python中bisect的使用方法

python中列表 list 的實現其實是乙個陣列,當要查詢某乙個元素的時候時間複雜度是o n 使用list.index 方法,但是隨著資料量的上公升,list.index 的效能也逐步下降,所以我們需要使用bisect模組來進行二分查詢,前提我們的列表是乙個有序的列表。遞迴二分查詢和迴圈二分查詢 ...