Python implementation recursive binary search, comparing the cyclic binary search performance and built-in module bisect

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]

Guess you like

Origin blog.csdn.net/qq_23869697/article/details/90243134