Transfer from cnblog North Los
http://www.cnblogs.com/beiluowuzheng/p/8452671.html
Implementation of the Python list (list) is actually an array, when you want to find a certain element when the time complexity is O (n), using list.index () method, but with the rising amount of data, list.index ( ) the gradual decline in performance, so we need to use bisect module for binary search, the premise of our list is an ordered list.
Recursive binary search and binary search loop
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
In order to compare the performance of both what we use two methods to test timeit module execution, timeit method timeit default function modules will need to test the implementation of 1,000,000, then return to the time of execution.
>>> 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
It can be seen circulating binary search to find the performance is better than the recursive half. Now, let's look to test the performance of a half bisect
Use bisect to search
>>> 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
Before comparison, we can see the look twice as fast as the bisect module with the performance look-half cycle than half. Again compare the performance if the Python native list.index () of
>>> def test_index():
... return lst.index(val)
...
>>> t4 = timeit.timeit("test_index()", setup="from __main__ import test_index")
>>> t4
518.1656223725007
It can be seen () to perform 1 million if list.index Python native, needs 500 seconds, compared to the previous binary search, the performance is simply slow to terror
Inserting a new element with bisect.insort
Sorting very time-consuming, so get in an ordered sequence After that, we'd be able to keep it orderly. bisect.insort is for this exist
insort (seq, item) item is inserted into the variable seq sequence in ascending order and can keep the 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)
Output:
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]