diff --git a/binary_search_tree/tree.py b/binary_search_tree/tree.py index cdd5abc..d6b0753 100644 --- a/binary_search_tree/tree.py +++ b/binary_search_tree/tree.py @@ -1,5 +1,5 @@ class TreeNode: - def __init__(self, key, val = None): + def __init__(self, key, val=None): if val == None: val = key @@ -7,53 +7,141 @@ def __init__(self, key, val = None): self.value = val self.left = None self.right = None - + + def height(self): + if self.right and self.left: + return 1 + max(self.left.height(), self.right.height()) + elif self.left: + return 1 + self.left.height() + elif self.right: + return 1 + self.right.height() + else: + return 1 class Tree: def __init__(self): self.root = None - # Time Complexity: - # Space Complexity: - def add(self, key, value = None): - pass + # Time Complexity: O(log N) + # Space Complexity: O(1) + + def add_helper(self, current_node, key, value): + if current_node == None: + return TreeNode(key, value) + if key <= current_node.key: + current_node.left = self.add_helper(current_node.left, key, value) + else: + current_node.right = self.add_helper( + current_node.right, key, value) + return current_node + + def add(self, key, value=None): + if self.root == None: + self.root = TreeNode(key, value) + else: + self.add_helper(self.root, key, value) + # parent = None + # current = self.root + # while current != None: + # parent = current + # if current.key >= key: + # current = current.left + # else: + # current = current.right + + # if parent.key > key: + # parent.left = TreeNode(key, value) + # else: + # parent.right = TreeNode(key, value) - # Time Complexity: - # Space Complexity: + # Time Complexity: O(n) + # Space Complexity: O(1) def find(self, key): - pass + if self.root == None: + return None + + current = self.root + while current != None: + if current.key == key: + return current.value + elif current.key < key: + current = current.right + else: + current = current.left + + return None + + # Time Complexity: O(n) + # Space Complexity: O(n) + def inorder_helper(self, current, traversal_list): + if not current: + return traversal_list + + obj = {'key': current.key, 'value': current.value} + self.inorder_helper(current.left, traversal_list) + traversal_list.append(obj) + self.inorder_helper(current.right, traversal_list) + return traversal_list - # Time Complexity: - # Space Complexity: def inorder(self): - pass + traversal_list = [] + return self.inorder_helper(self.root, traversal_list) + + # Time Complexity: O(n) + # Space Complexity:O(n) + def preorder_helper(self, current, traversal_list): + if not current: + return traversal_list + if current: + obj = {'key': current.key, 'value': current.value} + traversal_list.append(obj) + self.preorder_helper(current.left, traversal_list) + self.preorder_helper(current.right, traversal_list) + return traversal_list - # Time Complexity: - # Space Complexity: def preorder(self): - pass + traversal_list = [] + return self.preorder_helper(self.root, traversal_list) + + def postorder_helper(self, current, traversal_list): + if not current: + return traversal_list + if current: + self.postorder_helper(current.left, traversal_list) + self.postorder_helper(current.right, traversal_list) + obj = {'key': current.key, 'value': current.value} + traversal_list.append(obj) + return traversal_list + + # Time Complexity: O(n) + # Space Complexity: O(n) - # Time Complexity: - # Space Complexity: def postorder(self): - pass + traversal_list = [] + return self.postorder_helper(self.root, traversal_list) + + # Time Complexity: O(n) + # Space Complexity: O(n) - # Time Complexity: - # Space Complexity: def height(self): - pass + if self.root: + return self.root.height() + else: + return 0 # # Optional Method -# # Time Complexity: -# # Space Complexity: +# # Time Complexity: +# # Space Complexity: + + def bfs(self): pass - - # # Useful for printing + + def to_s(self): return f"{self.inorder()}" diff --git a/tests/__pycache__/__init__.cpython-39.pyc b/tests/__pycache__/__init__.cpython-39.pyc index aa55c2e..d1260c8 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..de2a700 100644 --- a/tests/test_binary_search_tree.py +++ b/tests/test_binary_search_tree.py @@ -6,6 +6,7 @@ def empty_tree() -> Tree(): return Tree() + @pytest.fixture() def tree_with_nodes(empty_tree) -> Tree(): empty_tree.add(5, "Peter") @@ -17,14 +18,17 @@ def tree_with_nodes(empty_tree) -> Tree(): return empty_tree + def test_add_and_find(tree_with_nodes): assert tree_with_nodes.find(5) == "Peter" assert tree_with_nodes.find(15) == "Ada" assert tree_with_nodes.find(3) == "Paul" + def test_find_returns_none_for_empty_tree(empty_tree): assert empty_tree.find(5) == None + def test_find_returns_none_for_values_not_in_tree(tree_with_nodes): assert tree_with_nodes.find(6) == None @@ -33,30 +37,31 @@ def test_inorder_with_empty_tree(empty_tree): answer = empty_tree.inorder() assert empty_tree.inorder() == [] + def test_inorder_with_nodes(tree_with_nodes): expected_answer = [ { - "key": 1, + "key": 1, "value": "Mary" - }, + }, { - "key": 3, + "key": 3, "value": "Paul" - }, + }, { - "key": 5, + "key": 5, "value": "Peter" - }, + }, { - "key": 10, + "key": 10, "value": "Karla" - }, + }, { - "key": 15, + "key": 15, "value": "Ada" - }, + }, { - "key": 25, + "key": 25, "value": "Kari" } ] @@ -64,31 +69,33 @@ def test_inorder_with_nodes(tree_with_nodes): answer = tree_with_nodes.inorder() assert answer == expected_answer + def test_preorder_on_empty_tree(empty_tree): assert empty_tree.preorder() == [] + def test_preorder_on_tree_with_nodes(tree_with_nodes): expected_answer = [ { - "key": 5, + "key": 5, "value": "Peter" - }, + }, { - "key": 3, + "key": 3, "value": "Paul" }, { "key": 1, "value": "Mary" - }, + }, { "key": 10, "value": "Karla" - }, + }, { "key": 15, "value": "Ada" - }, + }, { "key": 25, "value": "Kari" @@ -98,27 +105,29 @@ def test_preorder_on_tree_with_nodes(tree_with_nodes): answer = tree_with_nodes.preorder() assert answer == expected_answer + def test_postorder_on_empty_tree(empty_tree): assert empty_tree.postorder() == [] + def test_postorder_on_tree_with_nodes(tree_with_nodes): expected_answer = [ { - "key": 1, + "key": 1, "value": "Mary" - }, + }, { "key": 3, "value": "Paul" }, { - "key": 25, + "key": 25, "value": "Kari" - }, + }, { "key": 15, "value": "Ada" - }, + }, { "key": 10, "value": "Karla" @@ -132,44 +141,49 @@ def test_postorder_on_tree_with_nodes(tree_with_nodes): answer = tree_with_nodes.postorder() assert answer == expected_answer + def test_height_of_empty_tree_is_zero(empty_tree): assert empty_tree.height() == 0 + def test_height_of_one_node_tree(empty_tree): empty_tree.add(5, "pasta") assert empty_tree.height() == 1 + def test_height_of_many_node_tree(tree_with_nodes): assert tree_with_nodes.height() == 4 tree_with_nodes.add(2, "pasta") tree_with_nodes.add(2.5, "bread") assert tree_with_nodes.height() == 5 - + + def test_bfs_with_empty_tree(empty_tree): assert empty_tree.bfs() == [] + def test_bfs_with_tree_with_nodes(tree_with_nodes): expected_answer = [ { - "key": 5, + "key": 5, "value": "Peter" - }, + }, { - "key": 3, + "key": 3, "value": "Paul" - }, + }, { - "key": 10, + "key": 10, "value": "Karla" - }, + }, { - "key": 1, + "key": 1, "value": "Mary" - }, + }, { "key": 15, "value": "Ada" - }, + }, { "key": 25, "value": "Kari" @@ -178,4 +192,3 @@ def test_bfs_with_tree_with_nodes(tree_with_nodes): answer = tree_with_nodes.bfs() assert answer == expected_answer -