Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 82 additions & 18 deletions binary_search_tree/tree.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from turtle import right

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this didn't get used, so it can be deleted.



class TreeNode:
def __init__(self, key, val = None):
if val == None:
Expand All @@ -14,35 +17,96 @@ class Tree:
def __init__(self):
self.root = None

# Time Complexity:
# Space Complexity:
# Time Complexity: O(1)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately as nodes are added to the tree, new nodes will have to be added deeper and deeper, meaning that this doesn't run in the constant time that O(1) implies. Assuming a balanced tree, the complexity will be O(log(n)).

For example, if there are 7 nodes in a perfectly balanced tree, there would be 1 on top, 2 on the next, and 4 on the next. To add an 8th node will require recursing 3 times to add the new one on the new fourth level. And log_2(8) is 3, since 2^3 is 8.

# Space Complexity: O(N)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, for a recursive implementation like this, the space used will be O(log(n)) because each recursion requires a bit of space on the stack as it recurses down.

def add_helper(self,node,key,value):
if node is None:
return TreeNode(key,value)
if key < node.key:
node.left = self.add_helper(node.left, key, value)
else:
node.right = self.add_helper(node.right, key, value)

return node

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation of add_helper works, but definitely does a bit of extra work in setting nodes. Essentially, every node on the path to where the new node ends up will have either its left or right node "updated", though most of these will be updated to the exact same node. The only one that gets a meaningful update is whenever the bottom of the tree is reached and gets its left/right node updated to the new node. These updates happen in lines 26 and 27.

This probably will not be too bad of a performance hit, but there is a way that you can do this and just update only the node you need.

But this overall fine enough!



def add(self, key, value = None):
pass
self.root = self.add_helper(self.root,key,value)

# Time Complexity:
# Space Complexity:




# Time Complexity: O(N)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For much of the same reason as I explained above in my comment about adding a node, finding a node takes O(log(n)) time assuming a balanced tree.

For example, with 7 items in a perfectly balanced tree, searching for one of the values in the nodes on the bottom will mean iterating 3 times. The exact number is actually ceiling(log_2(n)) + 1, where ceiling rounds up the fractional part to the next number, which keeps this at O(log(n)). (Not that we expected you to come up with this number, I just wanted to explain!)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess as was said in Learn, unbalanced trees do trend to O(n), but I think we can assume balanced trees ideally.

Either way, not going to take points off.

# Space Complexity: O(1) - no additional databases
def find(self, key):
pass
current = self.root

while current != None:
if current.key == key:
return current.value
elif key < current.key:
current = current.left
else:
current = current.right
return None

# Time Complexity:
# Space Complexity:

# Time Complexity: O(N)
# Space Complexity: O(N)
def inorder(self):
pass
array_of_nodes = []
def inorder_helper(root):
if root is not None:
inorder_helper(root.left)
array_of_nodes.append({"key": root.key,"value": root.value})
inorder_helper(root.right)
inorder_helper(self.root)
return array_of_nodes






# Time Complexity:
# Space Complexity:
# Time Complexity: O(N)
# Space Complexity: O(N)
def preorder(self):
pass
array_of_nodes = []
def preorder_helper(root):
if root is not None:
array_of_nodes.append({"key": root.key,"value": root.value})
preorder_helper(root.left)
preorder_helper(root.right)
preorder_helper(self.root)
return array_of_nodes



# Time Complexity:
# Space Complexity:
# Time Complexity: O(N)
# Space Complexity:O(N)
def postorder(self):
pass
array_of_nodes = []
def postorder_helper(root):
if root is not None:
postorder_helper(root.left)
postorder_helper(root.right)
array_of_nodes.append({"key": root.key,"value": root.value})
postorder_helper(self.root)
return array_of_nodes

# Time Complexity:
# Space Complexity:
# Time Complexity: O(1)
# Space Complexity:O(1)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like adding a node, you have to account for the time and space you recurse down the tree for both of these being O(log(n))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, as I've done some of the other grading, I think the right calculation to give here is O(n) for time and O(1) for space. Because every node is being hit, our time complexity is O(n), but since we are not using more space, the space complexity is indeed O(1).

Forgive me for the conclusion, I was going off our example solution but I think I'm realizing there's a mistake in it.

def height(self):
pass
def height_helper(root):
if root is None:
return 0
else:
left_height = height_helper(root.left)
right_height = height_helper(root.right)
return max(left_height, right_height) + 1
return height_helper(self.root)



# # Optional Method
Expand Down