def add_value(self, value: T) -> None: """ Add value to this BST :param value: :return: """ ... if self.root: return self.root.add_value(value) else: self.root = BSTNode(value) return True
def add_value(self, value: T) -> None: """ Add value to this BST Duplicate values should be placed on the right :param value: :return: """ if self.root: return self.root.insert(value) else: self.root = BSTNode(value) return None
def add_value(self, value: T) -> None: """ Add value to this BST Duplicate values should be placed on the right :param value: :return: """ node = BSTNode(value) if (self.root is None): self.root = node node.left = None node.right = None else: cur = self.root while (cur is not None): if (self.key(node.value) < self.key(cur.value)): if (cur.left is None): node.parent = cur cur.left = node cur = None else: cur = cur.left else: if (cur.right is None): node.parent = cur cur.right = node cur = None else: cur = cur.right node.left = None node.right = None self._num_nodes += 1
def test_get_node(self): tree = BST() tree.add_value(100) tree.add_value(80) tree.add_value(90) tree.add_value(200) tree.add_value(70) self.assertEqual(BSTNode(70), tree.get_node(70))
def insert_recurse(self, value: T, node: BSTNode[T], key: Callable[[T], K]) -> BSTNode[T]: #if node.value == value: # return # come back and allow dups #elif node.value > value: if key(node.value) > key(value): if node.left: return self.insert_recurse(value,node.left,key) else: node.left = BSTNode(value) return else: if node.right: return self.insert_recurse(value,node.right,key) else: node.right = BSTNode(value) return
def test_get_max_node2(self): tree = BST() tree.add_value(100) tree.add_value(80) tree.add_value(90) tree.add_value(200) tree.add_value(70) node_to_remove = tree.get_node(80) self.assertEqual(BSTNode(90), tree.get_max_node(node_to_remove))
def test_create_tree(self): tree = BST() fill_int_tree(tree) root = BSTNode(100) root.left = BSTNode(80) root.right = BSTNode(200) root.left.left = BSTNode(70) root.left.right = BSTNode(90) cmp_tree = BST(root) self.assertEqual(tree, cmp_tree)
def add_value_helper(self, value: T, root: BSTNode[T]) -> BSTNode[T]: if self.root is None: return BSTNode(value=value, parent=root) elif value < root.value: # add_left root.left = self.add_value_helper(value, root.left) root.left.parent = root else: # add right root.right = self.add_value_helper(value, root.right) root.right.parent = root return root
def bst_insert(self, start: BSTNode[T], value: T): if start is None: # found the spot to add the node start = BSTNode(value) elif self.key(value) < self.key(start.value): # add_left start.left = self.bst_insert(start.left, value) start.left.parent = start else: # add right start.right = self.bst_insert(start.right, value) start.right.parent = start return start
def test_remove_internal_node_with_two_children(self): tree = BST() fill_int_tree(tree) tree.add_value(50) tree.add_value(95) tree.remove_value(80) root = BSTNode(100) root.left = BSTNode(90) root.right = BSTNode(200) root.left.left = BSTNode(70) root.left.right = BSTNode(95) root.left.left.left = BSTNode(50) cmp_tree = BST(root) self.assertEqual(tree, cmp_tree)
def test_tree_not_eq(self): tree = BST() fill_int_tree(tree) root = BSTNode(100) root.left = BSTNode(80) root.right = BSTNode(200) root.left.left = BSTNode(70) root.left.right = BSTNode(92) cmp_tree = BST(root) cmp_tree._num_nodes = 5 self.assertNotEqual(tree, cmp_tree)
def add_value(self, value: T) -> None: """ Add value to this BST :param value: :return: """ self.bst_length += 1 if self.root: return self.insert_recurse(value, self.root, self.key) else: self.root = BSTNode(value) return
def add_value(self, value: T, curNode: BSTNode = None) -> None: """ Add value to this BST :param curNode: defaults to None, but is the current node that the algorithm is on :param value: the donation amount :return: None """ if curNode is None: curNode = self.root if self.root is None: # base case- tree is empty so create a node and make it the root self.root = BSTNode(value) self.length = self.length + 1 elif self.key(value) == self.key(curNode.value): if curNode.getright() == -1: curNode.right = BSTNode(value, parent=curNode) self.length += 1 else: newNode = curNode.right self.add_value(value, newNode) elif self.key(value) < self.key( curNode.value): # I think we have to call key on this?? if curNode.getleft( ) == -1: # in other words, if curNode doesn't have a left child.. curNode.left = BSTNode(value, parent=curNode) self.length = self.length + 1 else: newNode = curNode.left self.add_value( value, newNode ) # recursive call to continue to find the correct spot for entry else: # self.key(value) > self.key(curNode.right): if curNode.getright() == -1: curNode.right = BSTNode(value, parent=curNode) self.length = self.length + 1 else: self.add_value(value, curNode.right)
def test_create_tree(self): tree = BST() tree.add_value(100) tree.add_value(80) tree.add_value(200) tree.add_value(90) tree.add_value(70) root = BSTNode(100) root.left = BSTNode(80) root.right = BSTNode(200) root.left.left = BSTNode(70) root.left.right = BSTNode(90) cmp_tree = BST(root) self.assertEqual(tree, cmp_tree) # but we don't pass this
def test_create_tree(self): tree = BST() tree.add_value(100) tree.add_value(80) tree.add_value(200) tree.add_value(90) tree.add_value(70) root = BSTNode(100) root.left = BSTNode(80) root.right = BSTNode(200) root.left.left = BSTNode(70) root.left.right = BSTNode(90) cmp_tree = BST(root) self.assertEqual(tree, cmp_tree) self.assertEqual(tree.height, 2) self.assertEqual(len(tree), 5)
def test_delete_4(self): tree = BST() tree.add_value(100) tree.add_value(80) tree.add_value(200) tree.add_value(300) tree.add_value(150) tree.remove_value(200) root = BSTNode(100) root.left = BSTNode(80) root.right = BSTNode(150) root.right.right = BSTNode(300) cmp_tree = BST(root) self.assertEqual(tree, cmp_tree)
from Trees.src.nodes.bst_node import BSTNode from Trees.src.trees.bst_tree import BST if __name__ == '__main__': a = BSTNode(50) b = BSTNode(40) c = BSTNode(35) d = BSTNode(37) e = BSTNode(45) f = BSTNode(90) a.left = b b.left = c c.right = d b.right = e print ( "create tree with 5 nodes") tree = BST(a) print ("len ex 5: ", len(tree)) print ("add node", tree.add_value(100)) print ("len ex 6: ", len(tree)) print ("remove node", tree.remove_value(50)) print ("len ex 5: ", len(tree)) results = [] tree.inorder(results) for x in results: print (x.value) print ("\n Testing adding children")
from Trees.src.nodes.bst_node import BSTNode from Trees.src.trees.bst_tree import BST if __name__ == '__main__': a = BSTNode(50) b = BSTNode(40) c = BSTNode(35) d = BSTNode(37) e = BSTNode(45) a.left = b b.left = c c.right = d b.right = e tree = BST(a) print("Tree height:", tree.height()) print("Tree length:", len(tree)) node_min = tree.get_min_node() print("Tree min:", node_min.value) node_max = tree.get_max_node() print("Tree max:", node_max.value) node_45 = tree.get_node(45) print("Tree 45", node_45.value) node_50 = tree.get_node(50) print("Tree 50", node_50.value) new_tree = BST() new_tree.add_value(100) new_tree.add_value(75) new_tree.add_value(200) new_tree.add_value(300)
def test_create_node(self): node = BSTNode(100) self.assertEqual(node.value, 100) self.assertIsNone(node.left, None) self.assertIsNone(node.right, None)
def test_init_(self, root: Optional[BSTNode[T]] = None, key: Callable[[T], K] = lambda x: x) -> None: node = BSTNode(45) tree = BST(node) self.assertEqual(tree.get_node(45).value, 45)
class BST(Generic[T, K]): """ T: The value stored in the node K: The value used in comparing nodes """ def __init__(self, root: Optional[BSTNode[T]] = None, key: Callable[[T], K] = lambda x: x) -> None: """ You must have at least one member named root :param root: The root node of the tree if there is one. If you are provided a root node don't forget to count how many nodes are in it :param key: The function to be applied to a node's value for comparison purposes. It serves the same role as the key function in the min, max, and sorted builtin functions """ self.root = None self.key = None ... @property def height(self) -> int: """ Compute the height of the tree. If the tree is empty its height is -1 :return: """ if self.root: return self.root.Height() elif self.root is None: return -1 else: return 0 def __len__(self) -> int: """ :return: the number of nodes in the tree """ if self.root: return self.root.__len__() else: return 0 def add_value(self, value: T) -> None: """ Add value to this BST :param value: :return: """ ... if self.root: return self.root.add_value(value) else: self.root = BSTNode(value) return True def get_node(self, value: K) -> BSTNode[T]: """ Get the node with the specified value :param value: :raises MissingValueError if there is no node with the specified value :return: """ if self.root: return self.root.get_node(value) elif self.root is None: raise MissingValueError else: return False def get_max_node(self) -> BSTNode[T]: """ Return the node with the largest value in the BST :return: :raises EmptyTreeError if the tree is empty """ if self.root: return self.root.get_max_node() elif self.root is None: raise EmptyTreeError else: return 0 def get_min_node(self) -> BSTNode[T]: """ Return the node with the smallest value in the BST :return: """ if self.root: return self.root.get_min_node() elif self.root is None: raise EmptyTreeError else: return 0 def remove_value(self, value: T) -> None: """ Remove the node with the specified value. When removing a node with 2 children take the successor for that node to be the largest value smaller than the node (the max of the left subtree) :param value: :return: :raises MissingValueError if the node does not exist """ if self.root: self.root.remove_value(value) elif self.root is None: raise MissingValueError def __eq__(self, other: object) -> bool: if self is other: return True elif isinstance(other, BST): if len(self) == 0 and len(other) == 0: return True else: return len(self) == len(other) and self.root.value == other.root.value and \ all((BST(c1) == BST(c2) for c1, c2 in zip(self.root, other.root))) else: return False def __ne__(self, other: object) -> bool: return not (self == other)
def test_add_node_with_two_children(self): a = BSTNode(50) b = BSTNode(40) c = BSTNode(35) d = BSTNode(37) e = BSTNode(45) f = BSTNode(90) g = BSTNode(150) a.left = b b.left = c c.right = d b.right = e m = BSTNode(65, children = [a,f]) tree1 = BST(m) self.assertEqual(len(tree1), 7)
def test_add_parent(self): a = BSTNode(50) b = BSTNode(40) c = BSTNode(35) d = BSTNode(37) e = BSTNode(45) f = BSTNode(90) g = BSTNode(150) a.left = b b.left = c c.right = d b.right = e p = BSTNode(200) n = BSTNode(75, children = [f, g], parent = p) tree2 = BST(p) self.assertEqual(len(tree2), 4)
class BST(Generic[T, K]): """ T: The value stored in the node K: The value used in comparing nodes """ def __init__(self, root: Optional[BSTNode[T]] = None, key: Callable[[T], K] = lambda x: x) -> None: """ You must have at least one member named root :param root: The root node of the tree if there is one. If you are provided a root node don't forget to count how many nodes are in it :param key: The function to be applied to a node's value for comparison purposes. It serves the same role as the key function in the min, max, and sorted builtin functions """ self.root = root self.key = key @property def height(self) -> int: """ Compute the height of the tree. If the tree is empty its height is -1 :return: """ def get_height(node): if node.left and node.right: return 1 + max(get_height(node.left), get_height(node.right)) elif node.left: return 1 + get_height(node.left) elif node.right: return 1 + get_height(node.right) else: return 0 if self.root: return get_height(self.root) else: return -1 def __len__(self) -> int: """ :return: the number of nodes in the tree """ def get_length(node): if not node: return 0 else: if node.right and node.left: return 1 + get_length(node.left) + get_length(node.right) elif node.right: return 1 + get_length(node.right) elif node.left: return 1 + get_length(node.left) else: return 1 return get_length(self.root) def add_value(self, value: T) -> None: """ Add value to this BST Duplicate values should be placed on the right :param value: :return: """ if self.root: return self.root.insert(value) else: self.root = BSTNode(value) return None def remove_value(self, value: K) -> None: """ Remove the node with the specified value. When removing a node with 2 children take the successor for that node to be the largest value smaller than the node (the max of the left subtree) :param value: :return: :raises MissingValueError if the node does not exist """ if self.root: return self.root.remove(value) else: raise MissingValueError def get_node(self, value: K) -> BSTNode[T]: """ Get the node with the specified value :param value: :raises MissingValueError if there is no node with the specified value :return: """ if self.root: return self.root.get(int(value)) else: raise MissingValueError def get_max_node(self) -> BSTNode[T]: """ Return the node with the largest value in the BST :return: :raises EmptyTreeError if the tree is empty """ if self.root: return self.root.get_max() else: raise EmptyTreeError def get_min_node(self) -> BSTNode[T]: """ Return the node with the smallest value in the BST :return: """ if self.root: return self.root.get_min() else: raise EmptyTreeError def __eq__(self, other: object) -> bool: if self is other: return True elif isinstance(other, BST): if len(self) == 0 and len(other) == 0: return True else: return len(self) == len(other) and self.root.value == other.root.value and \ BST(self.root.left) == BST(other.root.left) and \ BST(self.root.right) == BST(other.root.right) else: return False def __ne__(self, other: object) -> bool: return not (self == other) def __deepcopy__(self, memodict) -> "BST[T,K]": """ I noticed that for some tests deepcopying didn't work correctly until I implemented this method so here it is for you :param memodict: :return: """ new_root = copy.deepcopy(self.root, memodict) new_key = copy.deepcopy(self.key, memodict) return BST(new_root, new_key)