diff --git a/.gitignore b/.gitignore index 2d15a85..f051805 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,7 @@ dmypy.json .pyre/ # Editor settings -.vscode/settings.json \ No newline at end of file +.vscode/settings.json + + +.DS_Store diff --git a/algorithms/1_BinarySearch/binarysearch.py b/algorithms/1_BinarySearch/binarysearch.py index ed3413e..f61f2ff 100644 --- a/algorithms/1_BinarySearch/binarysearch.py +++ b/algorithms/1_BinarySearch/binarysearch.py @@ -1,13 +1,16 @@ from util import time_it -@time_it +# time complexity: O(log n) +# space complexity: O(1) + +# @time_it def linear_search(numbers_list, number_to_find): for index, element in enumerate(numbers_list): if element == number_to_find: return index return -1 -@time_it +# @time_it def binary_search(numbers_list, number_to_find): left_index = 0 right_index = len(numbers_list) - 1 @@ -32,8 +35,6 @@ def binary_search_recursive(numbers_list, number_to_find, left_index, right_inde return -1 mid_index = (left_index + right_index) // 2 - if mid_index >= len(numbers_list) or mid_index < 0: - return -1 mid_number = numbers_list[mid_index] @@ -47,9 +48,123 @@ def binary_search_recursive(numbers_list, number_to_find, left_index, right_inde return binary_search_recursive(numbers_list, number_to_find, left_index, right_index) +# @time_it +# my implementation for prob 2 -- the least efficient +def binary_search_for_all_occurences(numbers_list, number_to_find, left_index, right_index, result=[]): + if right_index < left_index: + return result + + mid_index = (left_index + right_index) // 2 + + mid_number = numbers_list[mid_index] + + if mid_number == number_to_find: + result.append(mid_index) + result_1 = binary_search_for_all_occurences(numbers_list, number_to_find, mid_index + 1, right_index, result) + result_2 = binary_search_for_all_occurences(numbers_list, number_to_find, left_index, mid_index - 1, result) + result = set(result_1).union(set(result_2)) + return result + + if mid_number < number_to_find: + left_index = mid_index + 1 + else: + right_index = mid_index - 1 + + return binary_search_for_all_occurences(numbers_list, number_to_find, left_index, right_index, result) + +@time_it +# the given solution for prob 2 -- not the most efficient +def find_all_occurances(numbers, number_to_find): + index = binary_search(numbers, number_to_find) + indices = [index] + # find indices on left hand side + i = index-1 + while i >=0: + if numbers[i] == number_to_find: + indices.append(i) + else: + break + i = i - 1 + + # find indices on right hand side + i = index + 1 + while i= mid_right: + if numbers_list[mid_right] == number_to_find: + result.append(mid_right) + else: + break + mid_right = mid_right + 1 + + return sorted(result) + + if mid_number < number_to_find: + left_index = mid_index + 1 + else: + right_index = mid_index - 1 + + return result + + if __name__ == '__main__': - numbers_list = [12, 15, 17, 19, 21, 24, 45, 67] - number_to_find = 21 + ''' + numbers_list_1 = [12, 15, 17, 19, 21, 24, 45, 67] + number_to_find_1 = 80 + + index_1 = binary_search_recursive(numbers_list_1, number_to_find_1, 0, len(numbers_list_1)-1) + print(f"Number found at index {index_1} using binary search") + + print("\n- - - - - - - - - - - - - - - - -\n") + ''' + + # exercise prob 1) + # ans: because binary search is for only sorted arrays + # (the given list [1,4,6,9,10,5,7] is not sorted, + # so if it tries to find 5, + # it will search [1, 4, 6] because 5 < 10, + # which leads to returning -1) + + # exercise prob 2) Find index of all the occurances of a number from sorted list + numbers_list_2 = [1,4,6,9,11,15,15,15,17,21,34,34,56] + number_to_find_2 = 15 + + index_2 = binary_search_for_all_occurences(numbers_list_2, number_to_find_2, 0, len(numbers_list_2)-1) + print(f"Number found at index {index_2} using my first least efficient way") + + index_s = find_all_occurances(numbers_list_2, number_to_find_2) + print(f"Number found at index {index_s} using the given solution") - index = binary_search_recursive(numbers_list, number_to_find, 0, len(numbers_list)) - print(f"Number found at index {index} using binary search") \ No newline at end of file + index_3 = find_all_efficient(numbers_list_2, number_to_find_2) + print(f"Number found at index {index_3} using my new efficient way") + \ No newline at end of file diff --git a/algorithms/2_BubbleSort/bubble_sort.py b/algorithms/2_BubbleSort/bubble_sort.py index c39aa87..d94e1ea 100644 --- a/algorithms/2_BubbleSort/bubble_sort.py +++ b/algorithms/2_BubbleSort/bubble_sort.py @@ -1,4 +1,7 @@ +# time complexity: O(n^2) +# space complexity: O(1) + # you can use this to sort strings too def bubble_sort(elements): size = len(elements) @@ -14,7 +17,32 @@ def bubble_sort(elements): if not swapped: break +''' +exercise prob) +modify bubble sort s.t. it can sort following list of transactions with key +elements = [ + { 'name': 'mona', 'transaction_amount': 1000, 'device': 'iphone-10'}, + { 'name': 'dhaval', 'transaction_amount': 400, 'device': 'google pixel'}, + { 'name': 'kathy', 'transaction_amount': 200, 'device': 'vivo'}, + { 'name': 'aamir', 'transaction_amount': 800, 'device': 'iphone-8'}, + ] +''' +# elements: list of hash tables +def bubble_sort_exercise(elements, key): + size = len(elements) + + for i in range(size-1): + swapped = False + for j in range(size-1-i): + if elements[j][key] > elements[j+1][key]: + tmp = elements[j] + elements[j] = elements[j+1] + elements[j+1] = tmp + swapped = True + + if not swapped: + break if __name__ == '__main__': elements = [5,9,2,1,67,34,88,34] @@ -22,4 +50,18 @@ def bubble_sort(elements): elements = ["mona", "dhaval", "aamir", "tina", "chang"] bubble_sort(elements) - print(elements) \ No newline at end of file + print(elements) + + print("\n- - - - - - - - - - - - - - - - -\n") + + elements = [ + { 'name': 'mona', 'transaction_amount': 1000, 'device': 'iphone-10'}, + { 'name': 'dhaval', 'transaction_amount': 400, 'device': 'google pixel'}, + { 'name': 'kathy', 'transaction_amount': 200, 'device': 'vivo'}, + { 'name': 'aamir', 'transaction_amount': 800, 'device': 'iphone-8'}, + ] + + bubble_sort_exercise(elements, 'name') + print(f"sorted by name:\n{elements}\n") + bubble_sort_exercise(elements, 'transaction_amount') + print(f"sorted by transaction amount:\n{elements}\n") \ No newline at end of file diff --git a/algorithms/3_QuickSort/quick_sort.py b/algorithms/3_QuickSort/quick_sort.py index 36b7e73..4faca10 100644 --- a/algorithms/3_QuickSort/quick_sort.py +++ b/algorithms/3_QuickSort/quick_sort.py @@ -1,3 +1,8 @@ + +# average time complexity: O(nlogn) +# worst time complexity: O(n^2) +# space complexity: O() + # implementation of quick sort in python using hoare partition scheme def swap(a, b, arr): @@ -31,11 +36,35 @@ def partition(elements, start, end): return end +# implementation of quick sort in python using lumoto partition scheme (exercise prob) + +def quick_sort_lumoto(elements, low, high): + pass + +def partition_lumoto(elements, low, high): + pivot_index = high + pivot = elements[high] + while low != high : + while low < len(elements) and elements[low] <= pivot: + low += 1 + if low < len(elements): + high = low + while elements[high] > pivot: + high += 1 + if low < high: + swap(low, high, elements) + return pivot_index + + if __name__ == '__main__': elements = [11,9,29,7,2,15,28] # elements = ["mona", "dhaval", "aamir", "tina", "chang"] - quick_sort(elements, 0, len(elements)-1) + # quick_sort(elements, 0, len(elements)-1) + print(elements) + partition_lumoto(elements, 0, len(elements)-1) print(elements) + #partition_lumoto(elements, 1) + print(elements) tests = [ [11,9,29,7,2,15,28], @@ -48,6 +77,6 @@ def partition(elements, start, end): for elements in tests: quick_sort(elements, 0, len(elements)-1) - print(f'sorted array: {elements}') - - + print(f'sorted array by hoare partition: {elements}') + #quick_sort_lumoto(elements, 0, len(elements)-1) + #print(f'sorted array by lumoto partition: {elements}') \ No newline at end of file diff --git a/data_structures/10_Graph/mygraph.py b/data_structures/10_Graph/mygraph.py new file mode 100644 index 0000000..5765a7a --- /dev/null +++ b/data_structures/10_Graph/mygraph.py @@ -0,0 +1,53 @@ +class Graph: + def __init__(self, edges): + self.edges = edges + self.graph_dict = {} + for start, end in edges: + if start in self.graph_dict: + self.graph_dict[start].append(end) + else: + self.graph_dict[start] = [end] + print("Graph Dict:", self.graph_dict) + + def get_paths(self, start, end, path=[]): + pass + + def get_shortest_path(self, start, end, path=[]): + pass + +if __name__ == '__main__': + + routes = [ + ("Mumbai","Pune"), + ("Mumbai", "Surat"), + ("Surat", "Bangaluru"), + ("Pune","Hyderabad"), + ("Pune","Mysuru"), + ("Hyderabad","Bangaluru"), + ("Hyderabad", "Chennai"), + ("Mysuru", "Bangaluru"), + ("Chennai", "Bangaluru") + ] + + routes = [ + ("Mumbai", "Paris"), + ("Mumbai", "Dubai"), + ("Paris", "Dubai"), + ("Paris", "New York"), + ("Dubai", "New York"), + ("New York", "Toronto"), + ] + + route_graph = Graph(routes) + + start = "Mumbai" + end = "New York" + + print(f"All paths between: {start} and {end}: ",route_graph.get_paths(start,end)) + print(f"Shortest path between {start} and {end}: ", route_graph.get_shortest_path(start,end)) + + start = "Dubai" + end = "New York" + + print(f"All paths between: {start} and {end}: ",route_graph.get_paths(start,end)) + print(f"Shortest path between {start} and {end}: ", route_graph.get_shortest_path(start,end)) diff --git a/data_structures/2_Arrays/arrays.py b/data_structures/2_Arrays/arrays.py new file mode 100644 index 0000000..1e7cca8 --- /dev/null +++ b/data_structures/2_Arrays/arrays.py @@ -0,0 +1,53 @@ +# 1. expenses +print("\n##### 1. Expenses #####") +expense = [2200, 2350, 2600, 2130, 2190] + +print(f"1) In Feb, you spent extra \"{expense[1]-expense[0]}\" \ +compare to Jan.") + +print(f"2) Total expense in first quarter is \ +\"{expense[0]+expense[1]+expense[2]}\".") + +print(f"3) Is there any month you spent exactly $2000?\n\ + Ans: {any([x for x in expense if x == 2000])}") + +expense.append(1980) +print(f"4) Now expense of June is added, it is \"{expense[5]}\"") + +print(f"5) The expense of April was {expense[3]}, but") +expense[3] = expense[3]-200 +print(f" she returned one item, which costs $200, \ +so it is updated to \"{expense[3]}\".") + + +# 2. marvel +print("\n##### 2. Marvel #####") +heros = ['spider man', 'thor', 'hulk', 'iron man', 'captain america'] + +print(f"1) Length of the list is \"{len(heros)}\".") + +heros.append('black panther') +print(f"2) Added black panther at the end of the list: {heros}") + +heros.remove('black panther') +heros.insert(3, 'black panther') +print(f"3) After hulk, need black panther: {heros[:]}") + +heros[1:3] = ['doctor stange'] +print(f"4) Removed thor and hulk and added doctor strage: {heros[:]}") + +heros.sort() +print(f"5) Sort the list: {heros}") + + +# 3. odd_numbers +print("\n##### 3. Odd number list #####") + + +def odd_between_1_and_max(max): + return [i for i in range(1, max+1) if i % 2 == 1] + + +m = int(input("Type max number for your list: ")) +list = odd_between_1_and_max(m) +print(f"Your list is {list}") diff --git a/data_structures/3_LinkedList/Solution/doubly_linked_list_exercise.py b/data_structures/3_LinkedList/Solution/doubly_linked_list_exercise.py index 35b9c38..b482e85 100644 --- a/data_structures/3_LinkedList/Solution/doubly_linked_list_exercise.py +++ b/data_structures/3_LinkedList/Solution/doubly_linked_list_exercise.py @@ -4,6 +4,7 @@ def __init__(self, data=None, next=None, prev=None): self.next = next self.prev = prev + class DoublyLinkedList: def __init__(self): self.head = None @@ -44,7 +45,7 @@ def get_length(self): count = 0 itr = self.head while itr: - count+=1 + count += 1 itr = itr.next return count @@ -71,10 +72,10 @@ def insert_at_end(self, data): itr.next = Node(data, None, itr) def insert_at(self, index, data): - if index<0 or index>self.get_length(): + if index < 0 or index > self.get_length(): raise Exception("Invalid Index") - if index==0: + if index == 0: self.insert_at_begining(data) return @@ -92,10 +93,10 @@ def insert_at(self, index, data): count += 1 def remove_at(self, index): - if index<0 or index>=self.get_length(): + if index < 0 or index >= self.get_length(): raise Exception("Invalid Index") - if index==0: + if index == 0: self.head = self.head.next self.head.prev = None return @@ -110,7 +111,7 @@ def remove_at(self, index): break itr = itr.next - count+=1 + count += 1 def insert_values(self, data_list): self.head = None @@ -120,16 +121,21 @@ def insert_values(self, data_list): if __name__ == '__main__': ll = DoublyLinkedList() - ll.insert_values(["banana","mango","grapes","orange"]) + ll.insert_values(["banana", "mango", "grapes", "orange"]) ll.print_forward() ll.print_backward() ll.insert_at_end("figs") ll.print_forward() - ll.insert_at(0,"jackfruit") + ll.insert_at(0, "jackfruit") ll.print_forward() - ll.insert_at(6,"dates") + ll.insert_at(6, "dates") ll.print_forward() - ll.insert_at(2,"kiwi") + ll.insert_at(2, "kiwi") + ll.print_forward() + print("--------------------------") + ll.remove_at(0) + ll.print_forward() + ll.remove_at(ll.get_length()-1) + ll.print_forward() + ll.remove_at(3) ll.print_forward() - - diff --git a/data_structures/3_LinkedList/double_linked_list.py b/data_structures/3_LinkedList/double_linked_list.py new file mode 100644 index 0000000..b0ac9d9 --- /dev/null +++ b/data_structures/3_LinkedList/double_linked_list.py @@ -0,0 +1,205 @@ +class Node: + def __init__(self, data=None, next=None, prev=None): + self.data = data + self.next = next + self.prev = prev + + +class DoubleLinkedList: + def __init__(self): + self.head = None + self.tail = None + # not having tail pointer would function similarly + # but only appending item to the list is O(n) + # because you have to traverse the whole list to get to the end + + def isHead(self, node): + return(node == self.head) + + def isTail(self, node): + return(node == self.tail) + + def print_forward(self): + # This method prints list in forward direction. Use node.next + if self.head is None: + print("Double linked list is empty") + return + itr = self.head + llstr = '' + while itr: + llstr += str(itr.data) + ' --> ' if itr.next else str(itr.data) + itr = itr.next + print(llstr) + + def print_with_info(self): + if self.head is None: + print("Double linked list is empty") + return + itr = self.head + llstr = '' + while itr: + if self.isHead(itr): + llstr += '(head) ' + if self.isTail(itr): + llstr += '(tail) ' + llstr += str(itr.data) + ' --> ' if itr.next else str(itr.data) + itr = itr.next + print(llstr) + + def print_backward(self): + # Print linked list in reverse direction. Use node.prev for this. + if self.tail is None: + print("Double linked list is empty") + return + itr = self.tail + llstr = '' + while itr: + llstr += str(itr.data) + ' <-- ' if itr.prev else str(itr.data) + itr = itr.prev + print(llstr) + + def get_length(self): + count = 0 + itr = self.head + while itr: + count += 1 + itr = itr.next + return count + + def insert_at_beginning(self, data): + if self.get_length() == 0: # Same as self.head == None + node = Node(data) + self.head = node + self.tail = node + else: + node = Node(data, self.head) + self.head.prev = node + self.head = node + + def insert_at_end(self, data): + if self.get_length() == 0: # Same as self.head == None + self.insert_at_beginning(data) + else: + node = Node(data, None, self.tail) + self.tail.next = node + self.tail = node + + def insert_at(self, index, data): + # index doesn't match + if index < 0 or index > self.get_length(): + raise Exception("Invalid Index") + # insert at head + if index == 0: + self.insert_at_beginning(data) + return + # other cases + itr = self.head + count = 0 + while itr: + if count == index - 1: + node = Node(data, itr.next, itr) + if itr.next: + itr.next.prev = node + if self.isTail(itr): + self.tail = node + itr.next = node + break + itr = itr.next + count += 1 + + def remove_at(self, index): + len = self.get_length() + # index doesn't match + if index < 0 or index >= len: + raise Exception("Invalid Index") + # remove head + if index == 0: + if self.isTail(self.head): + self.tail = None + self.head = None + else: + self.head = self.head.next + self.head.prev = None + return + # remove tail + if index == len - 1: + self.tail = self.tail.prev + self.tail.next = None + return + # other cases + itr = self.head + count = 0 + while itr.next: + if count == index - 1: + if self.isTail(itr.next): + itr.next.next = None + else: + itr.next.next.prev = itr + itr.next = itr.next.next + break + itr = itr.next + count += 1 + + def insert_values(self, data_list): + self.head = None + self.tail = None + for data in data_list: + self.insert_at_end(data) + + def insert_after_value(self, data_after, data_to_insert): + itr = self.head + while itr: + if itr.data == data_after: + node = Node(data_to_insert, itr.next, itr) + itr.next.prev = node + itr.next = node + break + itr = itr.next + + def remove_by_value(self, data): + itr = self.head + while itr: + if itr.data == data: + if self.isHead(itr): + if self.isTail(itr): + self.head = None + self.tail = None + else: + self.head = itr.next + self.head.prev = None + elif self.isTail(itr): + self.tail = self.tail.prev + self.tail.next = None + else: + itr.prev.next = itr.next + itr.next.prev = itr.prev + break + itr = itr.next + + +if __name__ == '__main__': + ''' + ll = DoubleLinkedList() + ll.insert_values([45, 7, 12, 567, 99]) + ll.remove_by_value(99) + ll.print_forward() + ''' + ll = DoubleLinkedList() + ll.insert_values(["banana", "mango", "grapes", "orange"]) + ll.print_forward() + ll.print_backward() + ll.insert_at_end("figs") + ll.print_with_info() + ll.insert_at(0, "jackfruit") + ll.print_with_info() + ll.insert_at(6, "dates") # this is where tail got messed up + ll.print_with_info() + ll.insert_at(2, "kiwi") + ll.print_with_info() + print("--------------------------") + ll.remove_at(0) + ll.print_with_info() + ll.remove_at(ll.get_length()-1) + ll.print_with_info() + ll.remove_at(3) + ll.print_with_info() diff --git a/data_structures/3_LinkedList/3_linked_list.py b/data_structures/3_LinkedList/linked_list.py similarity index 56% rename from data_structures/3_LinkedList/3_linked_list.py rename to data_structures/3_LinkedList/linked_list.py index a6d9466..12acdec 100644 --- a/data_structures/3_LinkedList/3_linked_list.py +++ b/data_structures/3_LinkedList/linked_list.py @@ -3,6 +3,7 @@ def __init__(self, data=None, next=None): self.data = data self.next = next + class LinkedList: def __init__(self): self.head = None @@ -15,6 +16,7 @@ def print(self): llstr = '' while itr: llstr += str(itr.data)+' --> ' if itr.next else str(itr.data) + # llstr += str(itr.data) + ' --> ' itr = itr.next print(llstr) @@ -22,9 +24,8 @@ def get_length(self): count = 0 itr = self.head while itr: - count+=1 + count += 1 itr = itr.next - return count def insert_at_begining(self, data): @@ -35,19 +36,15 @@ def insert_at_end(self, data): if self.head is None: self.head = Node(data, None) return - itr = self.head - while itr.next: itr = itr.next - itr.next = Node(data, None) def insert_at(self, index, data): - if index<0 or index>self.get_length(): + if index < 0 or index > self.get_length(): raise Exception("Invalid Index") - - if index==0: + if index == 0: self.insert_at_begining(data) return @@ -58,15 +55,14 @@ def insert_at(self, index, data): node = Node(data, itr.next) itr.next = node break - itr = itr.next count += 1 def remove_at(self, index): - if index<0 or index>=self.get_length(): + if index < 0 or index >= self.get_length(): raise Exception("Invalid Index") - if index==0: + if index == 0: self.head = self.head.next return @@ -76,24 +72,51 @@ def remove_at(self, index): if count == index - 1: itr.next = itr.next.next break - itr = itr.next - count+=1 + count += 1 def insert_values(self, data_list): self.head = None for data in data_list: self.insert_at_end(data) + def insert_after_value(self, data_after, data_to_insert): + # Search for first occurance of data_after value in linked list + # Now insert data_to_insert after data_after node + itr = self.head + while itr: + if itr.data == data_after: + node = Node(data_to_insert, itr.next) + itr.next = node + break + itr = itr.next + + def remove_by_value(self, data): + # Remove first node that contains data + if self.head.data == data: + self.head = self.head.next # Can Node be None? + return + itr = self.head + while itr.next: + if itr.next.data == data: + itr.next = itr.next.next + break + itr = itr.next + if __name__ == '__main__': + ll = LinkedList() - ll.insert_values(["banana","mango","grapes","orange"]) - ll.insert_at(1,"blueberry") - ll.remove_at(2) + ll.insert_values(["banana", "mango", "grapes", "orange"]) ll.print() - - ll.insert_values([45,7,12,567,99]) - ll.insert_at_end(67) + ll.insert_after_value("mango", "apple") # insert apple after mango + ll.print() + ll.remove_by_value("orange") # remove orange from linked list + ll.print() + ll.remove_by_value("figs") + ll.print() + ll.remove_by_value("banana") + ll.remove_by_value("mango") + ll.remove_by_value("apple") + ll.remove_by_value("grapes") ll.print() - diff --git a/data_structures/4_HashTable/hash_table.py b/data_structures/4_HashTable/hash_table.py new file mode 100644 index 0000000..2d05fa7 --- /dev/null +++ b/data_structures/4_HashTable/hash_table.py @@ -0,0 +1,80 @@ +# [ array ] +import os +stock_price_list = [] +abs_path = os.path.dirname(os.path.abspath(__file__)) +file_name = abs_path + '/stock_prices.csv' +with open(file_name, "r") as f: + for line in f: + tokens = line.split(',') + day = tokens[0] + price = float(tokens[1]) + stock_price_list.append([day, price]) + +print(stock_price_list) +# to find stock price on march 9 +for element in stock_price_list: + if element[0] == 'march 9': + print(element[1]) +# --> complexity of search using a list is O(n) + + +# [ dictionary (hashmap) ] +stock_price_dict = {} +with open(file_name, "r") as f: + for line in f: + tokens = line.split(',') + stock_price_dict[tokens[0]] = float(tokens[1]) + +print(stock_price_dict) +# to find stock price on march 9 +stock_price_dict['march 9'] +# --> complexity of search using a dictionaty is O(1) + + +# [ Implement Hash Table ] + +# hash function converts your string key into an index into array +# hash functions 1) using ASCII numbers +# --> add all ASCII numbers of string key and +# reduce number using mod (to get indexes less than array size) +# (e.g. if array size is 10, mod(609, 10) -> 9 + +# ord() returns an integer representing the Unicode character +# ASCII encoding : ascii value to binary (Western characters) +# each character becomes 8bits/1byte of binary data +# there are also Unicode encodings ... + +class HashTable: + def __init__(self): + self.MAX = 100 + self.arr = [None for i in range(self.MAX)] + + def get_hash(self, key): + hash = 0 + for char in key: + hash += ord(char) + return hash % self.MAX + + def __getitem__(self, index): + h = self.get_hash(index) + return self.arr[h] + + def __setitem__(self, key, val): + h = self.get_hash(key) + self.arr[h] = val + + def __delitem__(self, key): + h = self.get_hash(key) + self.arr[h] = None + + +if __name__ == '__main__': + t = HashTable() + t["march 6"] = 310 + print(t["march 6"]) + print(t["march 10"]) + del t["march 6"] + print(t["march 6"]) + +# lookup by key: O(1) on average +# insertion/deletion: O(1) on average diff --git a/data_structures/4_HashTable_2_Collisions/4_hash_table_collision_handling.ipynb b/data_structures/4_HashTable_2_Collisions/4_hash_table_collision_handling.ipynb index 0cebc4e..1547a47 100644 --- a/data_structures/4_HashTable_2_Collisions/4_hash_table_collision_handling.ipynb +++ b/data_structures/4_HashTable_2_Collisions/4_hash_table_collision_handling.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 56, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -28,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -37,7 +37,7 @@ "9" ] }, - "execution_count": 51, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -49,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 22, "metadata": { "scrolled": false }, @@ -60,7 +60,7 @@ "9" ] }, - "execution_count": 12, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -71,7 +71,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 23, "metadata": {}, "outputs": [], "source": [ @@ -83,7 +83,7 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -92,7 +92,7 @@ "459" ] }, - "execution_count": 55, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -110,7 +110,7 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 25, "metadata": {}, "outputs": [], "source": [ @@ -152,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ @@ -165,7 +165,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 27, "metadata": { "scrolled": true }, @@ -176,7 +176,7 @@ "310" ] }, - "execution_count": 88, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -187,7 +187,7 @@ }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 28, "metadata": { "scrolled": true }, @@ -198,7 +198,7 @@ "63457" ] }, - "execution_count": 89, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -209,7 +209,7 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -227,7 +227,7 @@ " [('march 6', 310), ('march 17', 63457)]]" ] }, - "execution_count": 90, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -238,7 +238,7 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": 30, "metadata": { "scrolled": true }, @@ -249,7 +249,7 @@ }, { "cell_type": "code", - "execution_count": 92, + "execution_count": 31, "metadata": {}, "outputs": [ { @@ -267,7 +267,7 @@ " [('march 6', 11), ('march 17', 63457)]]" ] }, - "execution_count": 92, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -278,16 +278,16 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "310" + "11" ] }, - "execution_count": 68, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -298,7 +298,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 36, "metadata": {}, "outputs": [ { @@ -310,7 +310,28 @@ } ], "source": [ - "del t[\"march 6\"]" + "del t[\"march 6\"]\n", + "del t[\"march 17\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[('march 7', 420)], [('march 8', 67)], [], [], [], [], [], [], [], []]" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.arr" ] } ], @@ -330,7 +351,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.5" } }, "nbformat": 4, diff --git a/data_structures/4_HashTable_2_Collisions/Solution/exercise_hash_table_linear_probing.ipynb b/data_structures/4_HashTable_2_Collisions/Solution/exercise_hash_table_linear_probing.ipynb index 88f9122..ef98ec8 100644 --- a/data_structures/4_HashTable_2_Collisions/Solution/exercise_hash_table_linear_probing.ipynb +++ b/data_structures/4_HashTable_2_Collisions/Solution/exercise_hash_table_linear_probing.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 115, + "execution_count": 125, "metadata": {}, "outputs": [], "source": [ @@ -68,6 +68,141 @@ " print(self.arr)" ] }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# test1 shows failing to get item\n", + "test1 = HashTable()\n", + "test1.get_hash(\"march 9\")" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test1.get_hash(\"march 10\")" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test1.get_hash(\"march 29\")" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[None, None, ('march 9', 1), None, None, None, None, None, None, None]\n", + "[None, None, ('march 9', 1), ('march 10', 2), None, None, None, None, None, None]\n", + "[None, None, ('march 9', 1), ('march 10', 2), ('march 29', 3), None, None, None, None, None]\n" + ] + } + ], + "source": [ + "\n", + "test1[\"march 9\"] = 1\n", + "test1[\"march 10\"] = 2\n", + "test1[\"march 29\"] = 3" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": {}, + "outputs": [], + "source": [ + "del test1[\"march 9\"]\n", + "test1[\"march 10\"] # failing to get item correctly" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[None, None, ('march 9', 1), None, None, None, None, None, None, None]\n", + "[None, None, ('march 9', 1), ('march 10', 2), None, None, None, None, None, None]\n", + "[None, None, ('march 9', 1), ('march 10', 2), ('march 29', 3), None, None, None, None, None]\n" + ] + } + ], + "source": [ + "# test2 shows failing to set item\n", + "test2 = HashTable()\n", + "test2[\"march 9\"] = 1\n", + "test2[\"march 10\"] = 2\n", + "test2[\"march 29\"] = 3" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[None, None, ('march 9', 1), ('march 29', 100), ('march 29', 3), None, None, None, None, None]\n" + ] + } + ], + "source": [ + "del test2[\"march 10\"]\n", + "test2[\"march 29\"] = 100 # failing to set item correctly" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -77,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": 116, + "execution_count": 132, "metadata": { "scrolled": true }, @@ -88,7 +223,7 @@ "[5, 6, 7, 0, 1, 2, 3]" ] }, - "execution_count": 116, + "execution_count": 132, "metadata": {}, "output_type": "execute_result" } @@ -99,7 +234,7 @@ }, { "cell_type": "code", - "execution_count": 117, + "execution_count": 133, "metadata": {}, "outputs": [ { @@ -119,7 +254,7 @@ }, { "cell_type": "code", - "execution_count": 118, + "execution_count": 134, "metadata": {}, "outputs": [ { @@ -136,7 +271,7 @@ }, { "cell_type": "code", - "execution_count": 119, + "execution_count": 135, "metadata": {}, "outputs": [ { @@ -153,7 +288,7 @@ }, { "cell_type": "code", - "execution_count": 120, + "execution_count": 136, "metadata": {}, "outputs": [ { @@ -170,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 121, + "execution_count": 137, "metadata": {}, "outputs": [], "source": [ @@ -179,7 +314,7 @@ }, { "cell_type": "code", - "execution_count": 122, + "execution_count": 138, "metadata": {}, "outputs": [ { @@ -188,7 +323,7 @@ "234" ] }, - "execution_count": 122, + "execution_count": 138, "metadata": {}, "output_type": "execute_result" } @@ -199,7 +334,7 @@ }, { "cell_type": "code", - "execution_count": 123, + "execution_count": 139, "metadata": { "scrolled": true }, @@ -218,7 +353,7 @@ }, { "cell_type": "code", - "execution_count": 124, + "execution_count": 140, "metadata": {}, "outputs": [ { @@ -227,7 +362,7 @@ "999" ] }, - "execution_count": 124, + "execution_count": 140, "metadata": {}, "output_type": "execute_result" } @@ -238,7 +373,7 @@ }, { "cell_type": "code", - "execution_count": 125, + "execution_count": 141, "metadata": { "scrolled": true }, @@ -257,7 +392,7 @@ }, { "cell_type": "code", - "execution_count": 126, + "execution_count": 142, "metadata": {}, "outputs": [ { @@ -274,7 +409,7 @@ }, { "cell_type": "code", - "execution_count": 127, + "execution_count": 143, "metadata": { "scrolled": true }, @@ -293,7 +428,7 @@ }, { "cell_type": "code", - "execution_count": 128, + "execution_count": 144, "metadata": {}, "outputs": [ { @@ -310,7 +445,7 @@ }, { "cell_type": "code", - "execution_count": 129, + "execution_count": 145, "metadata": {}, "outputs": [ { @@ -327,7 +462,7 @@ }, { "cell_type": "code", - "execution_count": 130, + "execution_count": 146, "metadata": {}, "outputs": [ { @@ -344,7 +479,7 @@ }, { "cell_type": "code", - "execution_count": 131, + "execution_count": 147, "metadata": { "scrolled": true }, @@ -354,12 +489,12 @@ "evalue": "Hashmap full", "output_type": "error", "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mException\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mt\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"Jan 1\"\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;32m\u001b[0m in \u001b[0;36m__setitem__\u001b[1;34m(self, key, val)\u001b[0m\n\u001b[0;32m 27\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mh\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mval\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 28\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 29\u001b[1;33m \u001b[0mnew_h\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfind_slot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mh\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 30\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mnew_h\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mval\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 31\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32m\u001b[0m in \u001b[0;36mfind_slot\u001b[1;34m(self, key, index)\u001b[0m\n\u001b[0;32m 41\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mprob_index\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 42\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mprob_index\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 43\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Hashmap full\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 44\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 45\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__delitem__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mException\u001b[0m: Hashmap full" + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/nk/nzndlkn14wx_mdp2_t31tqmc0000gn/T/ipykernel_88106/1223874474.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"Jan 1\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/var/folders/nk/nzndlkn14wx_mdp2_t31tqmc0000gn/T/ipykernel_88106/176672100.py\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, key, val)\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mh\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 29\u001b[0;31m \u001b[0mnew_h\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind_slot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mh\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 30\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnew_h\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/var/folders/nk/nzndlkn14wx_mdp2_t31tqmc0000gn/T/ipykernel_88106/176672100.py\u001b[0m in \u001b[0;36mfind_slot\u001b[0;34m(self, key, index)\u001b[0m\n\u001b[1;32m 41\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mprob_index\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 42\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mprob_index\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 43\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Hashmap full\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 44\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__delitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mException\u001b[0m: Hashmap full" ] } ], @@ -369,7 +504,7 @@ }, { "cell_type": "code", - "execution_count": 133, + "execution_count": null, "metadata": { "scrolled": true }, @@ -388,7 +523,7 @@ }, { "cell_type": "code", - "execution_count": 134, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -420,7 +555,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.5" } }, "nbformat": 4, diff --git a/data_structures/4_HashTable_2_Collisions/hash_table.py b/data_structures/4_HashTable_2_Collisions/hash_table.py new file mode 100644 index 0000000..e794608 --- /dev/null +++ b/data_structures/4_HashTable_2_Collisions/hash_table.py @@ -0,0 +1,202 @@ +# Exercise: Hash Table + +''' +1. [nyc_weather.csv](https://github.com/codebasics/data-structures-algorithms-python/blob/master/data_structures/4_HashTable_2_Collisions/Solution/nyc_weather.csv) + contains new york city weather for first few days in the month of January. + Write a program that can answer following, + 1. What was the average temperature in first week of Jan + 2. What was the maximum temperature in first 10 days of Jan + +Figure out data structure that is best for this problem +''' +import os +temp_list = [] +abs_path = os.path.dirname(os.path.abspath(__file__)) +temp_file = abs_path + '/Solution/nyc_weather.csv' +with open(temp_file, "r") as f: + for line in f: + tokens = line.split(',') + if tokens[0] == 'date': + pass + else: + temp_list.append(int(tokens[1])) +print("\nExercise Problem 1)") +print(f"The best data structure to use here was a list\n\ +because all we wanted was access of temperature elements") +print(f"The avaerage temperature in first week of Jan: \ +{round(sum(temp_list[:7])/7,2)}") +print(f"The maximum temperature in first 10 days of Jan: {max(temp_list)}") + + +''' +2. [nyc_weather.csv](https://github.com/codebasics/data-structures-algorithms-python/blob/master/data_structures/4_HashTable_2_Collisions/Solution/nyc_weather.csv) + contains new york city weather for first few days in the month of January. + Write a program that can answer following, + 1. What was the temperature on Jan 9? + 2. What was the temperature on Jan 4? + +Figure out data structure that is best for this problem +''' +temp_dict = {} +with open(temp_file, "r") as f: + for line in f: + tokens = line.split(',') + if tokens[0] == 'date': + pass + else: + temp_dict[tokens[0]] = int(tokens[1]) +print("\nExercise Problem 2)") +print(f"The best data structure to use here was a dictionary (internally a hash table)\n\ +because we wanted to know temperature for specific day, requiring key, value pair access\n\ +where you can look up an element by day using O(1) complexity") +print(f"The temperature on Jan 9: {temp_dict['Jan 9']}") +print(f"The temperature on Jan 4: {temp_dict['Jan 4']}") + + +''' +3. [poem.txt](https://github.com/codebasics/data-structures-algorithms-python/blob/master/data_structures/4_HashTable_2_Collisions/Solution/poem.txt) + contains famous poem "Road not taken" by poet Robert Frost. + You have to read this file in python and print every word and its count as show below. + Think about the best data structure that you can use to solve this problem + and figure out why you selected that specific data structure. + + 'diverged': 2, + 'in': 3, + 'I': 8 +''' +word_dict = {} +poem_file = abs_path + '/Solution/poem.txt' +with open(poem_file, "r") as f: + for line in f: + for word in line.split(): + key = word.strip('—.;,\n') + if key in word_dict: + word_dict[key] += 1 + else: + word_dict[key] = 1 +print("\nExercise Problem 3)") +print(f"Best data structure: Dictionary\n{word_dict}") + + +''' +4. Implement hash table where collisions are handled using linear probing. + We learnt about linear probing in the video tutorial. + Take the hash table implementation that uses chaining and modify methods to use **linear probing**. + Keep MAX size of arr in hashtable as 10. +''' + + +class HashTable: + def __init__(self): + self.MAX = 10 + self.arr = [(None, None) for i in range(self.MAX)] + + def get_hash(self, key): + hash = 0 + for char in key: + hash += ord(char) + return hash % self.MAX + + # returns the list of all indexs + # that need being probed + def get_prob_range(self, index): + return [*range(index, len(self.arr))] + [*range(0, index)] + + def __getitem__(self, key): + # new solution with helper function + # need to search all prob range because + # there might have been a case that some entries between + # were deleted after the item was set + h = self.get_hash(key) + for i in self.get_prob_range(h): + if self.arr[i][0] == key: + return self.arr[i][1] + return + + def __setitem__(self, key, val): + h = self.get_hash(key) + set = False + for i in self.get_prob_range(h): + if self.arr[i][0] == key: + self.arr[i] = (key, val) + set = True + return + for i in self.get_prob_range(h): + if self.arr[i][0] == None: + self.arr[i] = (key, val) + set = True + return + if not set: + raise Exception("Hashmap is full") + + def __delitem__(self, key): + h = self.get_hash(key) + for i in self.get_prob_range(h): + if self.arr[i][0] == key: + self.arr[i] = (None, None) + + +print("\nExercise Problem 4)") +print(f"Tested fine.\n\ +Even took care of the corner case that the solution didn't take care of,\n\ +which is get or set item that has been stored at somewhere else when the arr[h] gets deleted.\n\ +Lesson learned: use helper fuction!!!! (the current code is too hard to read)") + + +""" +print("\ntest 1) getting item correctly after some deletions") +# this two tests below(using march 9, 10, 29) are +# what the given solution code fails to pass +test1 = HashTable() +print(test1.get_hash("march 9")) +print(test1.get_hash("march 10")) +print(test1.get_hash("march 29")) +test1["march 9"] = 1 +test1["march 10"] = 2 +test1["march 29"] = 3 +print(test1.arr) +del test1["march 9"] +print(test1["march 10"]) +print(test1.arr) + +print("\ntest 2) setting item correctly after some deletions") +test2 = HashTable() +test2["march 9"] = 1 +test2["march 10"] = 2 +test2["march 29"] = 3 +del test2["march 10"] +test2["march 29"] = 100 +print(test2.arr) + + +print("\nmore tests)") +t = HashTable() +t["march 6"] = 20 +t["march 17"] = 88 +print(t.arr) +t["march 17"] = 29 +print(t.arr) +t["nov 1"] = 1 +print(t.arr) +t["march 33"] = 234 +print(t.arr) +print(t["dec 1"]) +print(t["march 33"]) +t["march 33"] = 999 +print(t.arr) +t["april 1"] = 87 +print(t.arr) +t["april 2"] = 123 +print(t.arr) +t["april 3"] = 234234 +print(t.arr) +t["april 4"] = 91 +print(t.arr) +t["May 22"] = 4 +print(t.arr) +t["May 7"] = 47 +print(t.arr) +# t["Jan 1"] = 0 --> raise exception +del t["april 2"] +print(t.arr) +""" diff --git a/data_structures/5_Stack/stack.py b/data_structures/5_Stack/stack.py new file mode 100644 index 0000000..5bf4b48 --- /dev/null +++ b/data_structures/5_Stack/stack.py @@ -0,0 +1,80 @@ +# Exercise: Stack + +''' +1. Write a function in python that can reverse a string using stack data structure. + Use `5_stack.ipynb` from the tutorial. + + reverse_string("We will conquere COVID-19") should return "91-DIVOC ereuqnoc lliw eW" +''' +from collections import deque + + +def reverse_string(str): + reversed = "" + stack = deque() + stack.extend(str) + l = len(stack) + while l != 0: + reversed += stack.pop() + l -= 1 + return reversed + + +r1 = reverse_string("hello") +print(f"reverse string of hello: {r1}") +r2 = reverse_string("We will conquere COVID-19") +print(f"reverse string of We will conquere COVID-19: {r2}") + +''' +2. Write a function in python that checks if paranthesis in the string are balanced or not. + Possible parantheses are "{}',"()" or "[]". + Use `5_stack.ipynb` from the tutorial. + + is_balanced("({a+b})") --> True + is_balanced("))((a+b}{") --> False + is_balanced("((a+b))") --> True + is_balanced("))") --> False + is_balanced("[a+b]*(x+2y)*{gg+kk}") --> True + +''' + + +def is_match(chr): + dict = {'}': '{', ']': '[', ')': '('} + return dict[chr] + + +def is_balanced(str): + stack = deque() + for chr in str: + if chr in "{([": + stack.append(chr) + if chr in "})]": + if len(stack) == 0 or is_match(chr) != stack.pop(): + return False + return len(stack) == 0 + """ + # first solution I wrote has a problem + # it doesn't consider when it has equal number of parenthese each side but not the wrong one + # {[}] --> gives me True, which is False indeed + stack = deque() + for chr in str: + if chr in "{([": + stack.append(chr) + if chr in "})]": + try: + stack.pop() + except IndexError: + return False + return len(stack) == 0 + """ + + +print("is_balanced(\"({a+b}))\"): " + str(is_balanced("({a+b})"))) +print("is_balanced(\"))((a+b}{\"): " + str(is_balanced("))((a+b}{"))) +print("is_balanced(\"((a+b))\"): " + str(is_balanced("((a+b))"))) +print("is_balanced(\"))\"): " + str(is_balanced("))"))) +print("is_balanced(\"[a+b]*(x+2y)*{gg+kk}\") : " + + str(is_balanced("[a+b]*(x+2y)*{gg+kk}"))) + +print("is_balanced(\"({a+b)})\"): " + str(is_balanced("({a+b)}"))) diff --git a/data_structures/6_Queue/6_queue.ipynb b/data_structures/6_Queue/6_queue.ipynb index 325ddb5..81729b4 100644 --- a/data_structures/6_Queue/6_queue.ipynb +++ b/data_structures/6_Queue/6_queue.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -25,7 +25,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -45,7 +45,7 @@ "[135, 132.12, 131.1]" ] }, - "execution_count": 6, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -56,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -65,7 +65,7 @@ "131.1" ] }, - "execution_count": 7, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -76,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -85,7 +85,7 @@ "[135, 132.12]" ] }, - "execution_count": 8, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -96,7 +96,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -105,7 +105,7 @@ "132.12" ] }, - "execution_count": 9, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -116,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -125,7 +125,7 @@ "135" ] }, - "execution_count": 10, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -136,7 +136,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -144,10 +144,10 @@ "evalue": "pop from empty list", "output_type": "error", "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mIndexError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mwmt_stock_price_queue\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mIndexError\u001b[0m: pop from empty list" + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/nk/nzndlkn14wx_mdp2_t31tqmc0000gn/T/ipykernel_96232/1260761002.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mwmt_stock_price_queue\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m: pop from empty list" ] } ], @@ -164,7 +164,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -174,7 +174,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -197,7 +197,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -217,7 +217,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -237,7 +237,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -257,7 +257,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -275,9 +275,14 @@ "q.pop()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "scrolled": true }, @@ -307,11 +312,13 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "from collections import deque\n", + "import time\n", + "import threading\n", "\n", "class Queue:\n", " \n", @@ -328,12 +335,43 @@ " return len(self.buffer)==0\n", " \n", " def size(self):\n", - " return len(self.buffer)" + " return len(self.buffer)\n", + "\n", + " def place_order(self, orders):\n", + " for order in orders:\n", + " self.enqueue(order)\n", + " time.sleep(0.5)\n", + "\n", + " def serve_order(self):\n", + " while not self.is_empty:\n", + " time.sleep(2)\n", + " print(self.dequeue())\n", + "\n", + " def food_ordering_system(self, orders):\n", + " q = Queue()\n", + " t1 = threading.Thread(target=q.place_order, args=(orders,))\n", + " t2 = threading.Thread(target=q.serve_order)\n", + " t1.start()\n", + " time.sleep(1)\n", + " t2.start()\n", + " t1.join()\n", + " t2.join()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "orders = ['pizza', 'samosa', 'pasta', 'biryani', 'burger']\n", + "q = Queue()\n", + "q.food_ordering_system(orders)" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -358,7 +396,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -378,7 +416,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -398,7 +436,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -433,7 +471,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.5" } }, "nbformat": 4, diff --git a/data_structures/6_Queue/myqueue.py b/data_structures/6_Queue/myqueue.py new file mode 100644 index 0000000..570a12d --- /dev/null +++ b/data_structures/6_Queue/myqueue.py @@ -0,0 +1,65 @@ +# Data structure tutorial exercise: Queue +from collections import deque +import threading +import time + + +class Queue: + + def __init__(self): + self.buffer = deque() + + def enqueue(self, val): + self.buffer.appendleft(val) + + def dequeue(self): + return self.buffer.pop() + + def is_empty(self): + return len(self.buffer) == 0 + + def size(self): + return len(self.buffer) + + # exercise prob 1) food ordering system + + def place_order(self, orders): + for order in orders: + self.enqueue(order) + time.sleep(0.5) + + def serve_order(self): + while not self.is_empty: + time.sleep(2) + print(self.dequeue()) + + def food_ordering_system(self, orders): + q = Queue() + t1 = threading.Thread(target=q.place_order, args=(orders,)) + t2 = threading.Thread(target=q.serve_order) + t1.start() + time.sleep(1) + t2.start() + t1.join() + t2.join() + + +# exercise prob 2) print binary numbers from 1 to 10 +def binary_numbers(n): + q = Queue() + q.enqueue('1') + for i in range(n): + entry = q.dequeue() + print(entry) + q.enqueue(entry + '0') + q.enqueue(entry + '1') + + +if __name__ == '__main__': + # exercise prob 1) + orders = ['pizza', 'samosa', 'pasta', 'biryani', 'burger'] + q = Queue() + q.food_ordering_system(orders) # not sure how to test + + # exercise prob 2) + binary_numbers(10) diff --git a/data_structures/7_Tree/7_tree.py b/data_structures/7_Tree/7_tree.py index 02d977d..340607f 100644 --- a/data_structures/7_Tree/7_tree.py +++ b/data_structures/7_Tree/7_tree.py @@ -1,6 +1,6 @@ class TreeNode: - def __init__(self, data): - self.data = data + def __init__(self, name, designation=''): + self.data = {'name': name, 'designation': designation} self.children = [] self.parent = None @@ -16,15 +16,42 @@ def get_level(self): def print_tree(self): spaces = ' ' * self.get_level() * 3 prefix = spaces + "|__" if self.parent else "" - print(prefix + self.data) + print(prefix + self.data['name']) if self.children: for child in self.children: child.print_tree() + def print_tree_ex1(self, option): + spaces = ' ' * self.get_level() * 3 + prefix = spaces + "|__" if self.parent else "" + if option == "both": + print(prefix + self.data['name'] + + " (" + self.data['designation'] + ")") + elif option in ("name", "designation"): + print(prefix + self.data[option]) + else: + raise Exception("Invalid option") + if self.children: + for child in self.children: + child.print_tree_ex1(option) + + def print_tree_ex2(self, level): + lv = self.get_level() + spaces = ' ' * lv * 3 + prefix = spaces + "|__" if self.parent else "" + print(prefix + self.data['name']) + if level == lv: + return + else: + if self.children: + for child in self.children: + child.print_tree_ex2(level) + def add_child(self, child): child.parent = self self.children.append(child) + def build_product_tree(): root = TreeNode("Electronics") @@ -48,5 +75,77 @@ def build_product_tree(): root.print_tree() +# exercise prob 1) company hierarchy tree + + +def build_management_tree(): + ceo = TreeNode("Nilupul", "CEO") + cto = TreeNode("Chinmay", "CTO") + hr = TreeNode("Gels", "HR Head") + ceo.add_child(cto) + ceo.add_child(hr) + + infra = TreeNode("Vishwa", "Infrastructure Head") + cto.add_child(infra) + cto.add_child(TreeNode("Aamir", "Application Head")) + infra.add_child(TreeNode("Dhaval", "Cloud Manager")) + infra.add_child(TreeNode("Abhijit", "App Manager")) + + hr.add_child(TreeNode("Peter", "Recruitment Manager")) + hr.add_child(TreeNode("Waqas", "Policy Manager")) + + return ceo + +# exercise prob 2) location tree + + +def build_location_tree(): + root = TreeNode("Global") + + india = TreeNode("India") + gujarat = TreeNode("Gujarat") + gujarat.add_child(TreeNode("Ahmedabad")) + gujarat.add_child(TreeNode("Baroda")) + karnataka = TreeNode("Karnataka") + karnataka.add_child(TreeNode("Bangluru")) + karnataka.add_child(TreeNode("Mysore")) + india.add_child(gujarat) + india.add_child(karnataka) + + usa = TreeNode("USA") + nj = TreeNode("New Jersey") + nj.add_child(TreeNode("Princeton")) + nj.add_child(TreeNode("Trenton")) + ca = TreeNode("California") + ca.add_child(TreeNode("San Francisco")) + ca.add_child(TreeNode("Mountain View")) + ca.add_child(TreeNode("Palo Alto")) + usa.add_child(nj) + usa.add_child(ca) + + root.add_child(india) + root.add_child(usa) + + return root + + if __name__ == '__main__': - build_product_tree() \ No newline at end of file + build_product_tree() + + print("\n- - - - - - - - - - - - - - - - -\n") + + # exercise prob 1) + # extend data and print tree with options, name, designation, both + root_node_1 = build_management_tree() + root_node_1.print_tree_ex1("name") # prints only name hierarchy + # prints only designation hierarchy + root_node_1.print_tree_ex1("designation") + # prints both (name and designation) hierarchy + root_node_1.print_tree_ex1("both") + + print("\n- - - - - - - - - - - - - - - - -\n") + + # exercise prob 2) + # build location tree and print tree with tree level + root_node_2 = build_location_tree() + root_node_2.print_tree_ex2(2) diff --git a/data_structures/7_Tree/Exercise/location_hierarchy.py b/data_structures/7_Tree/Exercise/location_hierarchy.py index 1b9232e..05c125a 100644 --- a/data_structures/7_Tree/Exercise/location_hierarchy.py +++ b/data_structures/7_Tree/Exercise/location_hierarchy.py @@ -27,6 +27,7 @@ def add_child(self, child): child.parent = self self.children.append(child) + def build_location_tree(): root = TreeNode("Global") @@ -65,6 +66,4 @@ def build_location_tree(): if __name__ == '__main__': root_node = build_location_tree() - root_node.print_tree(3) - - + root_node.print_tree(5) diff --git a/data_structures/8_Binary_Tree_1/binary_tree_part_1.py b/data_structures/8_Binary_Tree_1/binary_tree_part_1.py index 2c453a7..1bfd05b 100644 --- a/data_structures/8_Binary_Tree_1/binary_tree_part_1.py +++ b/data_structures/8_Binary_Tree_1/binary_tree_part_1.py @@ -6,7 +6,7 @@ def __init__(self, data): def add_child(self, data): if data == self.data: - return # node already exist + return # node already exist if data < self.data: if self.left: @@ -19,7 +19,6 @@ def add_child(self, data): else: self.right = BinarySearchTreeNode(data) - def search(self, val): if self.data == val: return True @@ -48,22 +47,102 @@ def in_order_traversal(self): return elements + # practice problems - implement five methods below + + # finds minimum element in entire binary tree + def find_min(self): + if self.left: + return self.left.find_min() + else: + return self.data + + # finds maximum element in entire binary tree + + def find_max(self): + if self.right: + return self.right.find_max() + else: + return self.data + + # calcualtes sum of all elements + def calculate_sum(self): + sum = self.data + if self.left: + sum += self.left.calculate_sum() + if self.right: + sum += self.right.calculate_sum() + return sum + + # perofrms pre order traversal of a binary tree + def pre_order_traversal(self): + elements = [] + elements.append(self.data) + + if self.left: + elements += self.left.pre_order_traversal() + if self.right: + elements += self.right.pre_order_traversal() + return elements + + # performs post order traversal of a binary tree + def post_order_traversal(self): + elements = [] + if self.left: + elements += self.left.post_order_traversal() + if self.right: + elements += self.right.post_order_traversal() + + elements.append(self.data) + return elements + def build_tree(elements): - print("Building tree with these elements:",elements) + print("Building tree with these elements:", elements) root = BinarySearchTreeNode(elements[0]) - for i in range(1,len(elements)): + for i in range(1, len(elements)): root.add_child(elements[i]) return root + if __name__ == '__main__': - countries = ["India","Pakistan","Germany", "USA","China","India","UK","USA"] + countries = ["India", "Pakistan", "Germany", + "USA", "China", "India", "UK", "USA"] country_tree = build_tree(countries) print("UK is in the list? ", country_tree.search("UK")) print("Sweden is in the list? ", country_tree.search("Sweden")) numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) - print("In order traversal gives this sorted list:",numbers_tree.in_order_traversal()) \ No newline at end of file + print("In order traversal gives this sorted list:", + numbers_tree.in_order_traversal()) + + print("\n- - - - - - - - - - - - - - - - -\n") + + print(numbers_tree.find_min()) + print(numbers_tree.find_max()) + + print(sum([17, 4, 1, 20, 9, 23, 18, 34])) + print(numbers_tree.calculate_sum()) + + print("Pre order traversal gives this sorted list:", + numbers_tree.pre_order_traversal()) + + print("Post order traversal gives this sorted list:", + numbers_tree.post_order_traversal()) + + print("\n- - - - - - - - - - - - - - - - -\n") + + numbers = [17, 4, 1, 20, 9, 23, 18, 34] + + numbers = [15, 12, 7, 14, 27, 20, 23, 88] + + numbers_tree = build_tree(numbers) + print("Input numbers:", numbers) + print("Min:", numbers_tree.find_min()) + print("Max:", numbers_tree.find_max()) + print("Sum:", numbers_tree.calculate_sum()) + print("In order traversal:", numbers_tree.in_order_traversal()) + print("Pre order traversal:", numbers_tree.pre_order_traversal()) + print("Post order traversal:", numbers_tree.post_order_traversal()) diff --git a/data_structures/9_Binary_Tree_2/binary_tree_part_2.py b/data_structures/9_Binary_Tree_2/binary_tree_part_2.py index 8a4a4a5..7c6ba3d 100644 --- a/data_structures/9_Binary_Tree_2/binary_tree_part_2.py +++ b/data_structures/9_Binary_Tree_2/binary_tree_part_2.py @@ -6,7 +6,7 @@ def __init__(self, data): def add_child(self, data): if data == self.data: - return # node already exist + return # node already exist if data < self.data: if self.left: @@ -19,7 +19,6 @@ def add_child(self, data): else: self.right = BinarySearchTreeNode(data) - def search(self, val): if self.data == val: return True @@ -62,10 +61,17 @@ def delete(self, val): return self.right elif self.right is None: return self.left - + ''' min_val = self.right.find_min() self.data = min_val self.right = self.right.delete(min_val) + ''' + # if the node to be deletedd has two children + # it has to copy one from children + # and delete the duplicated node from children + max_val = self.left.find_max() + self.data = max_val + self.left = self.left.delete(max_val) return self @@ -81,23 +87,34 @@ def find_min(self): def build_tree(elements): - print("Building tree with these elements:",elements) + print("Building tree with these elements:", elements) root = BinarySearchTreeNode(elements[0]) - for i in range(1,len(elements)): + for i in range(1, len(elements)): root.add_child(elements[i]) return root + if __name__ == '__main__': numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) numbers_tree.delete(20) - print("After deleting 20 ",numbers_tree.in_order_traversal()) # this should print [1, 4, 9, 17, 18, 23, 34] + # this should print [1, 4, 9, 17, 18, 23, 34] + print("After deleting 20 ", numbers_tree.in_order_traversal()) numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) numbers_tree.delete(9) - print("After deleting 9 ",numbers_tree.in_order_traversal()) # this should print [1, 4, 17, 18, 20, 23, 34] + # this should print [1, 4, 17, 18, 20, 23, 34] + print("After deleting 9 ", numbers_tree.in_order_traversal()) numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) numbers_tree.delete(17) - print("After deleting 17 ",numbers_tree.in_order_traversal()) # this should print [1, 4, 9, 18, 20, 23, 34] + # this should print [1, 4, 9, 18, 20, 23, 34] + print("After deleting 17 ", numbers_tree.in_order_traversal()) + + print("\n- - - - - - - - - - - - - - - - -\n") + + numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) + numbers_tree.delete(10) + print("After deleting 10 (non-existent node) ", + numbers_tree.in_order_traversal())