def create_tree(): """This method creates a fully-populated binary-search-tree of depth 4, on the numbers: [0, 30]""" # # ___________________15_____________________ # / \ # ______7_______ __________23_________ # / \ / \ # __3__ ___11___ ____19___ ____27___ # / \ / \ / \ / \ # 1 5 9 _13 _17 _21 _25 _29 # / \ / \ / \ / \ / \ / \ / \ / \ # 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 # # If we add the above values in the correct order, the tree is balanced, for free. tree = BinarySearchTree([15, 7, 23, 3, 11, 19, 27, 1, 5, 9, 13, 17, 21, 25, 29, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) return tree
def test_create_from_list(self): """This method creates a fully-populated binary-search-tree of depth 4, on the numbers: [0, 30]""" # # ___________________15_____________________ # / \ # ______7_______ __________23_________ # / \ / \ # __3__ ___11___ ____19___ ____27___ # / \ / \ / \ / \ # 1 5 9 _13 _17 _21 _25 _29 # / \ / \ / \ / \ / \ / \ / \ / \ # 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 # # If we add the above values in the correct order, the tree is balanced, for free. tree = BinarySearchTree([ 15, 7, 23, 3, 11, 19, 27, 1, 5, 9, 13, 17, 21, 25, 29, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 ]) # DEBUG # print(str(root)) # spot check -- *not full* check: self.assertEqual(node.value(tree), 15) self.assertEqual(node.value(node.right(tree)), 23) self.assertEqual(node.value(node.left(node.right(tree))), 19) self.assertEqual(node.value(node.left(node.left(node.right(tree)))), 17) self.assertEqual( node.value(node.left(node.left(node.left(node.right(tree))))), 16) self.assertEqual( node.value(node.right(node.left(node.left(node.right(tree))))), 18) # again spot checks -- verify that the tree can find values it contains self.assertEqual(tree.search(tree, 8), 8) self.assertEqual(tree.search(tree, 16), 16) self.assertEqual(tree.search(tree, 18), 18) self.assertEqual(tree.search(tree, 24), 24)
def test_getitem(self): # CASE 1: get from empty tree b = BinarySearchTree() with self.assertRaises(KeyError): b[10] # CASE 2: get value stored at root b[10] = 100 self.assertEqual(b[10], 100) # CASE 3: get values stored in left or right subtrees b[5] = 50 b[15] = 150 b[18] = 180 b[13] = 130 b[3] = 30 b[8] = 80 b[4] = 40 self.assertEqual(b[5], 50) self.assertEqual(b[10], 100) self.assertEqual(b[18], 180) self.assertEqual(b[4], 40) # CASE 4: get value not in non-empty tree with self.assertRaises(KeyError): b[2]
def insert_delete_all(n: int, sorted_: bool) -> None: """Insert <n> items into an empty BinarySearchTree, and then remove them. If <sorted_> is True, the items should be inserted in sorted order. Otherwise, the items should be in *random* order. Hint: lookup how to use random.shuffle for this function. Precondition: n >= 0. Note: you'll need to first create your own BinarySearchTree here, and then call insert and delete on it. """ bst = BinarySearchTree(None) if sorted_: for num in range(n): bst.insert(num) # for num in range(n): # bst.delete(num) else: random_list = list(range(n)) random.shuffle(random_list) for num in random_list: bst.insert(num)
def test_add(self): """ tests for add """ # Create an instance of BinarySearchTree binary = BinarySearchTree() # bsTree must be empty self.assertEqual(binary.size(), 0) # Add a key-value pair binary.add(15, "Value for 15") # Size of bsTree must be 1 self.assertEqual(binary.size(), 1) # Add another key-value pair binary.add(10, "Value for 10") # Size of bsTree must be 2 self.assertEqual(binary.size(), 2) # The added keys must exist. self.assertEqual(binary.search(10), "Value for 10") self.assertEqual(binary.search(15), "Value for 15")
def test_min(self): # 6 # / \ # 4 10 # \ # 16 bst = BinarySearchTree() self.assertEqual(bst.min(), None) node_val1 = 6 bst.add(node_val1) node_val2 = 4 bst.add(node_val2) node_val3 = 10 bst.add(node_val3) node_val4 = 16 bst.add(node_val4) self.assertEqual(bst.size, 4) self.assertEqual(bst.min(), node_val2)
def three_level_tree(): """ 10 / \ 5 15 / \ / \ 2 7 12 17 """ bst = BinarySearchTree(10) node_5 = BinarySearchTree(5) bst.insert(node_5) node_15 = BinarySearchTree(15) bst.insert(node_15) node_2 = BinarySearchTree(2) bst.insert(node_2) node_7 = BinarySearchTree(7) bst.insert(node_7) node_12 = BinarySearchTree(12) bst.insert(node_12) node_17 = BinarySearchTree(17) bst.insert(node_17) return bst
def test_bst_deletevalue_recursive(self): bst = BinarySearchTree() bst.insert_recursive(12) bst.insert_recursive(5) bst.insert_recursive(15) bst.insert_recursive(3) bst.insert_recursive(7) bst.insert_recursive(1) bst.insert_recursive(9) bst.insert_recursive(8) bst.insert_recursive(11) bst.insert_recursive(13) bst.insert_recursive(14) bst.insert_recursive(17) bst.insert_recursive(20) bst.insert_recursive(18) bst.delete_value_recursive(9) bst.delete_value_recursive(13) bst.delete_value_recursive(20) bst.delete_value_recursive(1) assert_equal(bst.get_max_recursive(), 18) assert_true(bst.get_min_recursive(), 3)
def test_depth_nobalance(self): bst1 = BinarySearchTree() bst2 = BinarySearchTree() bst3 = BinarySearchTree() bst4 = BinarySearchTree() bst5 = BinarySearchTree() bst6 = BinarySearchTree() bst1.insert(0) bst1.insert(1) bst1.insert(2) self.assertEqual(bst1.depth(), 3) bst2.insert(1) bst2.insert(2) bst2.insert(0) self.assertEqual(bst2.depth(), 2) bst3.insert(2) bst3.insert(0) bst3.insert(1) self.assertEqual(bst3.depth(), 3) bst4.insert(2) bst4.insert(1) bst4.insert(0) self.assertEqual(bst4.depth(), 3) bst5.insert(0) bst5.insert(2) bst5.insert(1) self.assertEqual(bst5.depth(), 3) bst6.insert(1) bst6.insert(0) bst6.insert(2) self.assertEqual(bst6.depth(), 2)
def test_balance_nobalance(self): bst1 = BinarySearchTree() bst2 = BinarySearchTree() bst3 = BinarySearchTree() bst4 = BinarySearchTree() bst5 = BinarySearchTree() bst6 = BinarySearchTree() bst1.insert(0) bst1.insert(1) bst1.insert(2) self.assertEqual(bst1.balance(), 2) bst2.insert(1) bst2.insert(2) bst2.insert(0) self.assertEqual(bst2.balance(), 0) bst3.insert(2) bst3.insert(0) bst3.insert(1) self.assertEqual(bst3.balance(), -2) bst4.insert(2) bst4.insert(1) bst4.insert(0) self.assertEqual(bst4.balance(), -2) bst5.insert(0) bst5.insert(2) bst5.insert(1) self.assertEqual(bst5.balance(), 2) bst6.insert(1) bst6.insert(0) bst6.insert(2) self.assertEqual(bst6.balance(), 0)
def test_has_left_and_right_initially_none(self): bst = BinarySearchTree() self.assertEqual(None, bst.left) self.assertEqual(None, bst.right)
def test_instantiation_with_value(self): fake_value = "fake" bst = BinarySearchTree(fake_value) self.assertEqual(fake_value, bst.value)
def test_bst_getheight_recursive(self): bst = BinarySearchTree() node_data = [10, 20, 5, 4, 3, 7, 8, 9, 7, 7] for value in node_data: bst.insert_recursive(value) assert_equal(4, bst.get_height_recursive())
# import BinarySearchTree from bst import BinarySearchTree start_time = time.time() f = open('names_1.txt', 'r') names_1 = f.read().split("\n") # List containing 10000 names f.close() f = open('names_2.txt', 'r') names_2 = f.read().split("\n") # List containing 10000 names f.close() duplicates = [] # set bstree to BinarySearchTree containing 'names' bstree = BinarySearchTree('names') # for names in names_1, use insert (from bst.py) to insert names into bstree for names in names_1: bstree.insert(names) # for name in names_2, if bstree contains (from bst.py) name, append the duplicate names for name in names_2: if bstree.contains(name): duplicates.append(name) # Runtime will be O(n) I think # runtime: 0.09803485870361328 seconds, 64 duplicates # duplicates = [] # for name_1 in names_1: # for name_2 in names_2: # if name_1 == name_2: # duplicates.append(name_1)
def test_find_for_none(self): val = None bst = BinarySearchTree() test_val = bst.find(10) self.assertEqual(test_val, val)
def test_delete_single(self): """ Deleting the node of a single-level tree returns None. """ bst = BinarySearchTree(5) self.assertIsNone(bst.delete(5))
start_time = time.time() f = open('names_1.txt', 'r') names_1 = f.read().split("\n") # List containing 10000 names f.close() f = open('names_2.txt', 'r') names_2 = f.read().split("\n") # List containing 10000 names f.close() duplicates = [] # for name_1 in names_1: # for name_2 in names_2: # if name_1 == name_2: # duplicates.append(name_1) bst = BinarySearchTree(names_1[0]) for name in names_1[1:]: bst.insert(name) for name in names_2: if bst.contains(name): duplicates.append(name) end_time = time.time() print(f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") print(f"runtime: {end_time - start_time} seconds") # Starter Code Runtime: 10.759980916976929 seconds # Optimized Code Runtime: 0.11665010452270508 seconds # ---------- Stretch Goal -----------
# ORIGINAL: ~4.8 seconds # Replace the nested for loops below with your improvements # for name_1 in names_1: # for name_2 in names_2: # if name_1 == name_2: # duplicates.append(name_1) # FIRST PASS SOLUTION: ~0.86 seconds # BASK IN THE GLORY OF THIS FASTER CODE # for name_1 in names_1: # if name_1 in names_2: # duplicates.append(name_1) # BST SOLUTION: 0.18 seconds # Fill tree A bst_a = BinarySearchTree(names_1[0]) for name in range(1, len(names_1)): bst_a.insert(names_1[name]) # Fill tree B bst_b = BinarySearchTree(names_2[0]) for name in range(1, len(names_2)): bst_b.insert(names_2[name]) # Create func to apply to each node in tree A find_duplicates = lambda name: duplicates.append(name) if bst_b.contains( name) else None # YEET
Menu = Enum( 'Menu', ['insert', 'remove', 'search', 'dump', 'dump_rev', 'range_key', 'exit']) def select_Menu() -> Menu: """메뉴 선택""" s = [f'({m.value}){m.name}' for m in Menu] while True: print(*s, sep=' ', end='') n = int(input(' : ')) if 1 <= n <= len(Menu): return Menu(n) tree = BinarySearchTree() # 이진 검색 트리를 생성 while True: menu = select_Menu() # 메뉴 선택 if menu == Menu.insert: # 삽입 key = int(input('삽입할 키를 입력하세요.: ')) val = input('삽입할 값을 입력하세요.: ') if not tree.add(key, val): print('삽입에 실패했습니다!') elif menu == Menu.remove: # 삭제 key = int(input('삭제할 키를 입력하세요.: ')) tree.remove(key) elif menu == Menu.search: # 검색
def test_new_insert_method(self): value = 10 bst = BinarySearchTree() bst.insert(value) self.assertEqual(value, bst.value)
def test_find(self): test_val = 10 bst = BinarySearchTree(test_val) return_val = bst.find(test_val) self.assertEqual(test_val, return_val)
def test_search_single_one(self): """ Searching a single-level tree for a key that does exist returns that node / tree. """ bst = BinarySearchTree(5) self.assertEqual(bst, bst.search(5))
duplicates = [] # Return the list of duplicates in this data structure # Replace the nested for loops below with your improvements # 0(N^2) # for name_1 in names_1: # for name_2 in names_2: # if name_1 == name_2: # duplicates.append(name_1) # MY SOLUTION # Worse case of O(n) for searching if BST is heavily stacked to one side new_tree = BinarySearchTree("Joshua") for i in names_1: new_tree.insert(i) for i in names_2: if new_tree.contains(i): duplicates.append(i) end_time = time.time() print(f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") print(f"runtime: {end_time - start_time} seconds") # ---------- Stretch Goal ----------- # Python has built-in tools that allow for a very efficient approach to this problem # What's the best time you can accomplish? Thare are no restrictions on techniques or data # structures, but you may not import any additional libraries that you did not write yourself.
node = new_node return if new_node.data < node.data: if node.left is None: #if space on left #make the new node the new child node.left = new_node return else: #no space #repeat for left child #recurse insert(node.left, new_node) if new_node.data > node.data: if node.right is None: node.right = new_node return else: insert(node.right, new_node) insert(root, Node(1)) insert(root, Node(20)) result = search(20, root) print(result.data) bst = BinarySearchTree() bst.insert(bst.root, Node(1)) bst.insert(bst.root, Node(4))
def test_search_single_none(self): """ Searching a single-level tree for a key that doesn't exist returns None. """ bst = BinarySearchTree(5) self.assertIsNone(bst.search(-999))
def _simple_tree(): '''Create a simple test tree. See http://en.wikipedia.org/wiki/Binary_search_tree''' return BinarySearchTree(values=[8, 3, 1, 6, 4, 7, 10, 14, 13])
names_2 = f.read().split("\n") # List containing 10000 names f.close() duplicates = [] # Return the list of duplicates in this data structure # Replace the nested for loops below with your improvements # for name_1 in names_1: # for name_2 in names_2: # if name_1 == name_2: # duplicates.append(name_1) # FASTER CODE HERE!!! # turn names into a BST name_bst = BinarySearchTree(names_1[1]) # for every name in names_1 for name in names_1: # inserting those names into the names BST name_bst.insert(name) # for every item in names_2 for name in names_2: # if nameBST already contains the name in names_2 if name_bst.contains(name): # append name to duplicates list duplicates.append(name) end_time = time.time() print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n")
def test_bst_get_minvalue_iterative(self): bst = BinarySearchTree() inserts = [20, 10, 14, 15, 9, 4, 19, 26] for node in inserts: bst.insert(node) assert_equal(4, bst.get_min())
tree.inorder_traversal() tree.search(13) tree.search(7) tree.delete(13) tree.inorder_traversal() tree.search(11) tree.delete(5) tree.inorder_traversal() tree.search(3) tree = BinarySearchTree() for v in values: tree.insert(v) res = tree.traverse() print('->'.join([str(d) for d in res])) data = tree.search(13) assert(data.value == 13) data = tree.search(7) assert(data.value == 7) tree.delete(13) res = tree.traverse() print('->'.join([str(d) for d in res])) data = tree.search(11) assert(data.value == 11)
def test_bst_get_maxvalue_iterative(self): bst = BinarySearchTree() inserts = [24, 40, 42, 31, 8, 17, 84] for node in inserts: bst.insert(node) assert_equal(84, bst.get_max())