class BST_Test_Replace_With_10_Elements_Existing_Key(TestCase): def setUp(self): self._bst = BinarySearchTree() self._bst.insert(key=5, obj=5) self._bst.insert(key=8, obj=8) self._bst.insert(key=7, obj=7) self._bst.insert(key=9, obj=9) self._bst.insert(key=10, obj=10) self._bst.insert(key=2, obj=2) self._bst.insert(key=1, obj=1) self._bst.insert(key=3, obj=3) self._bst.insert(key=4, obj=4) self._bst.insert(key=6, obj=6) self._bst_node_count = 10 def test_replace_with_existing_key_on_tree(self): key_to_replace = 5 value_to_set = -5 self._bst.replace(key_to_replace, value_to_set) self.assertEqual( key_to_replace in self._bst, True, 'Tree has_key operation must return True for existing key') self.assertEqual(self._bst.find(key_to_replace), value_to_set, 'Find operation failed on tree after replace') self.assertNotEqual(self._bst.find(key_to_replace), key_to_replace, 'replaced key still exists!') def tearDown(self): self._bst = None
class BST_Test_Tree_Delete_Element_With_10_Elements(TestCase): def setUp(self): self._bst = BinarySearchTree() self._bst.insert(key=5, obj=5) self._bst.insert(key=8, obj=8) self._bst.insert(key=7, obj=7) self._bst.insert(key=9, obj=9) self._bst.insert(key=10, obj=10) self._bst.insert(key=2, obj=2) self._bst.insert(key=1, obj=1) self._bst.insert(key=3, obj=3) self._bst.insert(key=4, obj=4) self._bst.insert(key=6, obj=6) self._bst_node_count = 10 def test_delete_element_of_tree_non_existing_element(self): self._bst.remove(11) self.assertEqual(self._bst.node_count, self._bst_node_count, 'Tree node count must be 10') def test_delete_element_of_tree_with_10_node(self): elements_to_delete = [10, 1, 7, 3, 5, 8, 2, 6, 9] for element in elements_to_delete: self._bst.remove(element) self.assertEqual(self._bst.find(element), None, 'Element found in BST after deleting it!') self._bst_node_count = self._bst_node_count - 1 self.assertEqual(self._bst.node_count, self._bst_node_count, 'Tree node count must tally after deletion') def tearDown(self): self._bst = None
class BST_Test_Tree_Count_Find_Element_With_10_Elements(TestCase): def setUp(self): self._bst = BinarySearchTree() self._bst.insert(key=5, obj=5) self._bst.insert(key=8, obj=8) self._bst.insert(key=7, obj=7) self._bst.insert(key=9, obj=9) self._bst.insert(key=10, obj=10) self._bst.insert(key=2, obj=2) self._bst.insert(key=1, obj=1) self._bst.insert(key=3, obj=3) self._bst.insert(key=4, obj=4) self._bst.insert(key=6, obj=6) self._bst_node_count = 10 def test_node_count_of_tree_with_10_node(self): self.assertEqual(self._bst.node_count, self._bst_node_count, 'Tree node count must be 10') def test_find_element_of_tree_with_10_node(self): for i in range(1, 11): # 1 to 10 tree_element = self._bst.find(i) self.assertNotEqual( tree_element, None, 'BST findElement did not return existing element') self.assertEqual(tree_element, i, 'Find operation failed on tree with 1 node') def tearDown(self): self._bst = None
class BST_Test_Tree_With_1_Element(TestCase): def setUp(self): self._bst = BinarySearchTree() self._bst.insert(key=10, obj=10) def test_node_count_of_tree_with_1_node(self): self.assertEqual(self._bst.node_count, 1, 'Tree node count must be 1') def test_find_key_of_tree_with_1_node(self): self.assertEqual(self._bst.find(10), 10, 'Find operation failed on tree with 1 node') def test_delete_element_of_tree_with_1_node(self): self._bst.remove(10) self.assertEqual(self._bst.node_count, 0, 'Empty tree node count must be 0') self.assertEqual(self._bst.find(20), None, 'Empty tree find operation must return None') def tearDown(self): self._bst = None
class BSTHashBucket(collections.MutableMapping): ''' A hash bucket is used to hold objects that hash to the same value in a hash table. This is hash bucket using a binary search tree. This masquerades as a python dict in code where it is used. Since bst is used as bucket datastructure, searches take O log(n) rather than O n Note: HASHBUCKET ITERATION YIELDS KEYS. not the key value pairs in the bucket. ''' def __init__(self): self._bst = BinarySearchTree() def __len__(self): ''' The number of elements in the hash bucket ''' return self._bst.node_count def get(self, key, default = None): ''' Get object associated with a key and on key miss return specified default. This is there in Python dict and this class masquerades as dict, we implement it. ''' try: value = self[key] return value except KeyError: return default def __getitem__(self, key): value = self._bst.find(key) if value == None: raise KeyError('Key Error: %s ' % repr(key)) return value def __delitem__(self, key): if key in self._bst: self._bst.remove(key) else: raise KeyError('Key Error: %s ' % repr(key)) def __setitem__(self, key, obj): if key in self._bst: self._bst.replace(key, obj) else: self._bst.insert(key, obj) def __iter__(self): for key, value in self._bst.inorder_traversal_with_stack(): yield key
class BST_Test_Empty_Tree(TestCase): def setUp(self): self._bst = BinarySearchTree() def test_node_count_of_empty_tree(self): self.assertEqual(self._bst.node_count, 0, 'Empty tree node count must be 0') def test_find_key_empty_tree(self): self.assertEqual(self._bst.find(20), None, 'Empty tree find operation must return None') def test_delete_element_empty_tree(self): self._bst.remove(20) def tearDown(self): self._bst = None