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
defbinary_search_loop
(lst, val)
: start, end =0,
len(lst)-1
while start <= end:
mid =
(start + end)//2
if lst[mid]
< val:
start = mid +
1elif lst[mid]
> val:
end = mid -
1else
: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>>
>
deftest_recursion()
:...
return binary_search_recursion(lst, val,0,
len(lst)-1
)...
>>
>
deftest_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
>>
>
defbinary_search_bisect
(lst, val):.
.. i = bisect.bisect(lst, val)..
.if i !=
len(lst)
and lst[i]
== val:..
.return i..
.return
none..
.>>
>
deftest_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()
的效能
>>
>
deftest_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 =
10random.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模組來進行二分查詢,前提我們的列表是乙個有序的列表。遞迴二分查詢和迴圈二分查詢 ...