python: unit tests for binary search

This commit is contained in:
Almas Zaurbekov
2020-08-13 01:50:19 +06:00
parent d8da439590
commit 977000eb86
5 changed files with 173 additions and 28 deletions

View File

@@ -1,28 +0,0 @@
def binary_search(list, item):
# low and high keep track of which part of the list you'll search in.
low = 0
high = len(list) - 1
# While you haven't narrowed it down to one element ...
while low <= high:
# ... check the middle element
mid = (low + high) // 2
guess = list[mid]
# Found the item.
if guess == item:
return mid
# The guess was too high.
if guess > item:
high = mid - 1
# The guess was too low.
else:
low = mid + 1
# Item doesn't exist
return None
my_list = [1, 3, 5, 7, 9]
print(binary_search(my_list, 3)) # => 1
# 'None' means nil in Python. We use to indicate that the item wasn't found.
print(binary_search(my_list, -1)) # => None

View File

@@ -0,0 +1,58 @@
class BinarySearch():
def search_iterative(self, list, item):
# low and high keep track of which part of the list you'll search in.
low = 0
high = len(list) - 1
# While you haven't narrowed it down to one element ...
while low <= high:
# ... check the middle element
mid = (low + high) // 2
guess = list[mid]
# Found the item.
if guess == item:
return mid
# The guess was too high.
if guess > item:
high = mid - 1
# The guess was too low.
else:
low = mid + 1
# Item doesn't exist
return None
def search_recursive(self, list, low, high, item):
# Check base case
if high >= low:
mid = (high + low) // 2
guess = list[mid]
# If element is present at the middle itself
if guess == item:
return mid
# If element is smaller than mid, then it can only
# be present in left subarray
elif guess > item:
return self.search_recursive(list, low, mid - 1, item)
# Else the element can only be present in right subarray
else:
return self.search_recursive(list, mid + 1, high, item)
else:
# Element is not present in the array
return None
if __name__ == "__main__":
# We must initialize the class to use the methods of this class
bs = BinarySearch()
my_list = [1, 3, 5, 7, 9]
print(bs.search_iterative(my_list, 3)) # => 1
# 'None' means nil in Python. We use to indicate that the item wasn't found.
print(bs.search_iterative(my_list, -1)) # => None

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,107 @@
from binary_search import BinarySearch
import unittest
import json
import time
bs = BinarySearch()
# Unloading all lists from a file
with open("items.json", "r") as file:
data = json.load(file)
# Setting values to created variables
simple_list = data["simple_list"]
list_with_10_items = data["list_with_10_items"]
list_with_100_items = data["list_with_100_items"]
list_with_1000_items = data["list_with_1000_items"]
# Test cases to test Binary Search algorithm
class TestBinarySearch(unittest.TestCase):
def setUp(self):
print (".......... %s" % self._testMethodName)
# Checking the implementation of iterative binary search
def test_iterative_binary_search_with_simple_list(self):
# ARRANGE
# You can check the index of each item in the items.json file
item, expected_index = 3, 1
# ACT
# Run the method we created and get the index of the item we were looking for
index = bs.search_iterative(simple_list, item) # => 1
# ASSERT
# Compare the resulting index with the expected index
self.assertEqual(expected_index, index) # => 1 == 1
def test_recoursive_binary_search_with_simple_list(self):
item, expected_index = 3, 1
# To run recursive search for an item,
# we need to determine the minimum and maximum indexes of the list
low, high = 0, len(simple_list) - 1
index = bs.search_recursive(simple_list, low, high, item)
self.assertEqual(expected_index, index)
def test_search_for_nonexistent_item(self):
# Specifically set a number that is not in the list
item, expected_result = 100, None
# Trying to find an item that doesn't exist
index = bs.search_iterative(simple_list, item) # => None
self.assertEqual(expected_result, index)
def test_binary_search_and_linear_search_execution_time(self):
item, expected_index = 9887, 990
# Time required to search
start_time = time.time()
binary_search_index = bs.search_iterative(list_with_1000_items, item) # => None
bs_time = time.time() - start_time
# list.index(x) return the index in the list of the first item whose value is x.
# It is an error if there is no such item.
# Complexity of list.index(x) is O(n)
start_time = time.time()
linear_search_index = list_with_1000_items.index(item)
ls_time = time.time() - start_time
self.assertEqual(expected_index, binary_search_index)
self.assertEqual(expected_index, linear_search_index)
self.assertTrue(bs_time < ls_time)
# print("--- Time required to search item at the ending ---")
# print("--- Linear Search %f seconds ---" % (ls_time))
# print("--- Binary Search %f seconds ---" % (bs_time))
def test_execution_time_for_item_at_the_beginning(self):
item, expected_index = 55, 10
# Binary search - time required to search
start_time = time.time()
binary_search_index = bs.search_iterative(list_with_1000_items, item) # => None
bs_time = time.time() - start_time
# Linear search - time required to search
start_time = time.time()
linear_search_index = list_with_1000_items.index(item)
ls_time = time.time() - start_time
self.assertEqual(expected_index, binary_search_index)
self.assertEqual(expected_index, linear_search_index)
# linear search will be faster, since the item we are looking for
# is at the beginning of the list
self.assertTrue(bs_time > ls_time)
# print("--- Time required to search item at the beginning ---")
# print("--- Linear Search %f seconds ---" % (ls_time))
# print("--- Binary Search %f seconds ---" % (bs_time))
if __name__ == '__main__':
unittest.main()