I want to compare theoretical and practical ratios of linear search and binary search. It will be clear from my code, i hope:
import math
import random
import timeit
def linear_search(alist: list[int], elem: int) -> int | None:
for item in alist:
if item == elem:
return elem
return None
def binary_search(alist: list[int], elem: int) -> int | None:
lo, hi = 0, len(alist) - 1
while lo <= hi:
mid = (lo + hi) // 2
if elem == alist[mid]:
return elem
elif elem < alist[mid]:
hi = mid - 1
else:
lo = mid + 1
return None
def compare_searches():
# just some big value
N = 100_000
# just generate some sorted list
alist = [x for x in range(N)]
# elem = random.randrange(N)
# just some value to trigger the worst case scenarios during searches
elem = -42
# searches should give the same result
assert linear_search(alist, elem) == binary_search(alist, elem)
linear_time_avg = timeit.timeit(lambda: linear_search(alist, elem), number=10000)
binary_time_avg = timeit.timeit(lambda: binary_search(alist, elem), number=10000)
print("theoretical (complexities ratio): ", N / math.log2(N))
print("practical (times ratio): ", linear_time_avg / binary_time_avg)
if __name__ == "__main__":
compare_searches()
So this code produces:
theoretical (complexities ratio): 6020.599913279624
practical (times ratio): 898.7857719144624
I understand, that there should be some difference between complexities ratio and times ratio, but why is it so big? Like 6 times greater? I thought, that ratios will be roughfly the same tbh.