diff --git a/binary_search_tree/tree.py b/binary_search_tree/tree.py index cdd5abc..609a775 100644 --- a/binary_search_tree/tree.py +++ b/binary_search_tree/tree.py @@ -7,52 +7,174 @@ def __init__(self, key, val = None): self.value = val self.left = None self.right = None - class Tree: def __init__(self): self.root = None - # Time Complexity: - # Space Complexity: + # Time Complexity: O(log n) *if balanced + # Space Complexity: O(1) def add(self, key, value = None): - pass + # edge case: if tree is empty, add node at root + if self.root == None: + self.root = TreeNode(key, value) + return None + # find the parent node + else: + parent = None + curr_node = self.root + while curr_node != None: + parent = curr_node + if key < curr_node.key: + curr_node = curr_node.left + else: + curr_node = curr_node.right + + # determine on which side of the node to create the node + if key < parent.key: + parent.left = TreeNode(key, value) + else: + parent.right = TreeNode(key, value) + + def add_helper(self, curr_node, key, value): + if curr_node == None: + return TreeNode(key, value) + + if key < curr_node.key: + curr_node.left = self.add_helper(curr_node.left, key, value) + else: + curr_node.right = self.add_helper(curr_node.right, key, value) + return curr_node - # Time Complexity: - # Space Complexity: + # Time Complexity: O(log n) *if balanced + # Space Complexity: O(log n) *if balanced + def add_recursive(self, key, value = None): + if self.root == None: + self.root = TreeNode(key, value) + else: + # use helper method to add parameter + self.add_helper(self.root, key, value) + + + # Time Complexity: O(log n) *if balanced + # Space Complexity: O(1) def find(self, key): - pass + if self.root == None: + return None + + curr_node = self.root + while curr_node != None: + if curr_node.key == key: + return curr_node.value + elif key < curr_node.key: + curr_node = curr_node.left + else: + curr_node = curr_node.right + return None + + def find_helper(self, curr_node, key, value): + if curr_node == None: + return None + + if key < curr_node.key: + curr_node.left = self.find_helper(curr_node.left, key, value) + else: + curr_node.right = self.find_helper(curr_node, key, value) + return curr_node + + # Time Complexity: O(log n) *if balanced + # Space Complexity: O(log n) *if balanced + def find_recursive(self, key, value = None): + if self.root == None: + return None + else: + self.find_helper(self.root, key, value) + + def preorder_helper(self, curr_node, trav_list): + if curr_node == None: + return + else: + trav_list.append({"key": curr_node.key, "value": curr_node.value}) + self.preorder_helper(curr_node.left, trav_list) + self.preorder_helper(curr_node.right, trav_list) + + # Time Complexity: O(n) + # Space Complexity: O(n) + def preorder(self): + if self.root == None: + return [] + traversal_list = [] + self.preorder_helper(self.root, traversal_list) + return traversal_list + + def inorder_helper(self, curr_node, trav_list): + if curr_node == None: + return + else: + self.inorder_helper(curr_node.left, trav_list) + trav_list.append({"key": curr_node.key, "value": curr_node.value}) + self.inorder_helper(curr_node.right, trav_list) - # Time Complexity: - # Space Complexity: + # Time Complexity: O(n) + # Space Complexity: O(n) def inorder(self): - pass + if self.root == None: + return [] + traversal_list = [] + self.inorder_helper(self.root, traversal_list) + return traversal_list - # Time Complexity: - # Space Complexity: - def preorder(self): - pass + def postorder_helper(self, curr_node, trav_list): + if curr_node == None: + return + else: + self.postorder_helper(curr_node.left, trav_list) + self.postorder_helper(curr_node.right, trav_list) + trav_list.append({"key": curr_node.key, "value": curr_node.value}) - # Time Complexity: - # Space Complexity: + # Time Complexity: O(n) + # Space Complexity: O(n) def postorder(self): - pass + if self.root == None: + return [] + traversal_list = [] + self.postorder_helper(self.root, traversal_list) + return traversal_list + + def height_helper(self, curr_node): + if curr_node == None: + return 0 + left_height = self.height_helper(curr_node.left) + right_height = self.height_helper(curr_node.right) + return max(left_height, right_height) + 1 - # Time Complexity: - # Space Complexity: + # Time Complexity: O(n) + # Space Complexity: O(n) def height(self): - pass + if self.root == None: + return 0 + return self.height_helper(self.root) # # Optional Method -# # Time Complexity: -# # Space Complexity: +# # Time Complexity: O(n) +# # Space Complexity: O(n) def bfs(self): - pass - - + if self.root == None: + return [] + queue = [self.root] + bfs_list = [] + while len(queue) > 0: + curr_node = queue.pop(0) + if curr_node.left: + queue.append(curr_node.left) + if curr_node.right: + queue.append(curr_node.right) + bfs_list.append({"key": curr_node.key, "value": curr_node.value}) + + return bfs_list # # Useful for printing def to_s(self): diff --git a/tests/__pycache__/__init__.cpython-39.pyc b/tests/__pycache__/__init__.cpython-39.pyc index aa55c2e..da5a901 100644 Binary files a/tests/__pycache__/__init__.cpython-39.pyc and b/tests/__pycache__/__init__.cpython-39.pyc differ diff --git a/tests/test_binary_search_tree.py b/tests/test_binary_search_tree.py index c2339e2..63febc9 100644 --- a/tests/test_binary_search_tree.py +++ b/tests/test_binary_search_tree.py @@ -25,10 +25,12 @@ def test_add_and_find(tree_with_nodes): def test_find_returns_none_for_empty_tree(empty_tree): assert empty_tree.find(5) == None +def test_find_returns_value_in_tree(tree_with_nodes): + assert tree_with_nodes.find(25) == "Kari" + def test_find_returns_none_for_values_not_in_tree(tree_with_nodes): assert tree_with_nodes.find(6) == None - def test_inorder_with_empty_tree(empty_tree): answer = empty_tree.inorder() assert empty_tree.inorder() == []