class TestPut: @pytest.mark.parametrize('new_node, parent, root_height', [(Node(3, 'B'), 'A', 1), (Node(9, 'C'), 'A', 1), (Node(2, 'D'), 'B', 2), (Node(4, 'E'), 'B', 2), (Node(10, 'F'), 'C', 2)]) def test__put(self, rooted_bst, new_node, parent, root_height): bst = rooted_bst bst._put(new_node, bst.root) assert new_node.parent.value == parent assert rooted_bst.root.height == root_height def test_put_root(self, empty_bst): assert empty_bst.root == None assert empty_bst.size == 0 empty_bst.put(6, 'val') assert empty_bst.root != None assert empty_bst.size == 1 @pytest.mark.parametrize( 'node_list, rebalanced_node_list', [(right_heavy_right_child_right_heavy_bst, rebalanced_right_heavy_right_child_right_heavy_node_list), (right_heavy_right_child_left_heavy_bst, rebalanced_right_heavy_right_child_left_heavy_node_list), (left_heavy_left_child_left_heavy_bst, rebalanced_left_heavy_left_child_left_heavy_node_list), (left_heavy_left_child_right_heavy_bst, rebalanced_left_heavy_left_child_right_heavy_node_list)]) def test_put(self, node_list, rebalanced_node_list): bst = BST() for node in node_list: bst.put(node[0], node[1]) assert bst.breadth_first_traversal() == rebalanced_node_list
def test_node_construction(): n = Node('key', 'value') assert n.key == 'key' assert n.value == 'value' assert n.left_child == None assert n.right_child == None assert n.parent == None
def test_bubble_down(self): tree = AVL(Node(5)) tree._bubble_down_to_place(tree.get_root(), Node(12)) tree._bubble_down_to_place(tree.get_root(), Node(0)) tree._bubble_down_to_place(tree.get_root(), Node(6)) tree._bubble_down_to_place(tree.get_root(), Node(8)) node_5 = tree.get_root() node_12 = node_5.get_right_child() node_0 = node_5.get_left_child() node_6 = node_12.get_left_child() node_8 = node_6.get_right_child() expect(node_5.get_key()).to.be.equal(5) expect(node_12.get_key()).to.be.equal(12) expect(node_0.get_key()).to.be.equal(0) expect(node_6.get_key()).to.be.equal(6) expect(node_8.get_key()).to.be.equal(8)
def test_09_bf(self): l = [50, 30, 60, 150, 170, 130, 190, 210, 15, 10] tree = Node.from_list([100]) for i in l: tree.insert(i) tree.traverse(self.check) for i in [60, 170, 210, 15]: tree.delete(i) tree.traverse(self.check)
def test_07_height(self): tree = Node.from_list([100]) self.assertEqual(tree.height(), 1) tree.insert(50) self.assertEqual(tree.height(), 2) tree.insert(30) self.assertEqual(tree.height(), 3) tree.insert(60) self.assertEqual(tree.height(), 3) tree.insert(70) self.assertEqual(tree.height(), 4)
def test_06_rotate(self): tree = Node.from_list([100, 50, 40, 60, 150, 170, 190, 200]) tree.search(40).rotate_cw() self.assertEqual(tree.to_list(), (100, (40, None, (50, None, (60, None, None))), (150, None, (170, None, (190, None, (200, None, None))))) ) tree.traverse(self.check) tree.search(170).rotate_ccw() self.assertEqual(tree.to_list(), (100, (40, None, (50, None, (60, None, None))), (170, (150, None, None), (190, None, (200, None, None)))) ) tree.traverse(self.check) t1 = Node.from_list_raw((32, (23, None, None), (48, None, (59, None, None)))) t1.right.rotate_ccw() t1.traverse(self.check)
def avl_file_reader(file): # this function loads file in to avl tree avl_tree = AVL_Tree() # stores avl tree in to a vairable for line in file: word = line.strip('\n').lower() avl_tree.insert(Node(word)) file.close() return avl_tree
def test_04_delete(self): tree = self.tree tree.delete(12) self.assertEqual(tree.to_list(), (6, (4, (1, (0, None, None), (3, None, None)), None), (7, None, (9, None, None)))) tree.traverse(self.check) tree.delete(7) self.assertEqual(tree.to_list(), (6, (4, (1, (0, None, None), (3, None, None)), None), (9, None, None))) tree.traverse(self.check) self.assertRaises(KeyError, tree.delete, 7) tree.delete(1) self.assertEqual(tree.to_list(), (6, (4, (0, None, (3, None, None)), None), (9, None, None))) tree.traverse(self.check) tree.delete(6) self.assertEqual(tree.to_list(), (4, (0, None, (3, None, None)), (9, None, None))) tree.traverse(self.check) tree.delete(9) self.assertEqual(tree.to_list(), (4, (0, None, (3, None, None)), None)) tree.traverse(self.check) tree = Node.from_list_raw((150, (130, None, None), (170, None, (190, None, (210, None, None))))) tree.delete(170) self.assertEqual(tree.to_list(), (150, (130, None, None), (190, None, (210, None, None)))) tree.traverse(self.check) tree.delete(210) self.assertEqual(tree.to_list(), (150, (130, None, None), (190, None, None))) tree.traverse(self.check) tree.delete(150) self.assertEqual(tree.to_list(), (130, None, (190, None, None))) tree.traverse(self.check) tree.delete(130) self.assertEqual(tree.to_list(), (190, None, None)) tree.traverse(self.check) self.assertRaises(RuntimeError, tree.delete, 190)
def test_rotate_right_subtree_is_right_child_from_root(self): A = create_right_rotable_tree() root = Node(10, name='root') root.set_right_child(A) A.set_parent(root) root._set_height(3) rotable_to_right_tree = AVL(root) rotable_to_right_tree._right_rotate( rotable_to_right_tree.get_root().get_right_child()) root = rotable_to_right_tree.get_root() B = root.get_right_child() A = B.get_right_child() a = B.get_left_child() c = A.get_right_child() b = A.get_left_child() expect(root.get_name()).to.be.equal('root') expect(B.get_name()).to.be.equal('B') expect(A.get_name()).to.be.equal('A') expect(a.get_name()).to.be.equal('a') expect(b.get_name()).to.be.equal('b') expect(c.get_name()).to.be.equal('c') expect(root.get_height()).to.be.equal(3) expect(B.get_height()).to.be.equal(2) expect(A.get_height()).to.be.equal(1) expect(a.get_height()).to.be.equal(0) expect(b.get_height()).to.be.equal(0) expect(c.get_height()).to.be.equal(0) expect(root.get_node_count()).to.be.equal(6) expect(B.get_node_count()).to.be.equal(5) expect(A.get_node_count()).to.be.equal(3) expect(a.get_node_count()).to.be.equal(1) expect(b.get_node_count()).to.be.equal(1) expect(c.get_node_count()).to.be.equal(1)
def build_unbalanced_tree(self, bst, node_list): for node in node_list: new_node = Node(node[0], node[1]) new_node.height = node[2] if bst.root == None: bst.root = new_node else: current_node = bst.root while current_node: if new_node.key <= current_node.key: if current_node.left_child == None: new_node.parent = current_node current_node.left_child = new_node break else: current_node = current_node.left_child else: if current_node.right_child == None: new_node.parent = current_node current_node.right_child = new_node break else: current_node = current_node.right_child return bst
def test_update_heights(self): node_5 = Node(5) node_0 = Node(0) node_12 = Node(12) tree = AVL(node_5) tree._set_root(node_5) node_5.set_left_child(node_0) node_5.set_right_child(node_12) node_0.set_parent(node_5) node_12.set_parent(node_5) node_5._set_height(1) node_0._set_height(0) node_12._set_height(0) node_6 = Node(6) node_12.set_left_child(node_6) node_6.set_parent(node_12) tree._update_heights(node_6) expect(node_5.get_height()).to.be.equal(2) expect(node_0.get_height()).to.be.equal(0) expect(node_12.get_height()).to.be.equal(1) expect(node_6.get_height()).to.be.equal(0)
def create_not_zig_zag_tree_left(): node_12 = Node(12) node_11 = Node(11) node_10 = Node(10) node_12.set_left_child(node_11) node_11.set_parent(node_12) node_11.set_left_child(node_10) node_10.set_parent(node_11) node_12._set_height(2) node_11._set_height(1) node_10._set_height(0) return node_12
def create_zig_zag_tree_left_right(): node_12 = Node(12) node_6 = Node(6) node_8 = Node(8) node_12.set_left_child(node_6) node_6.set_parent(node_12) node_6.set_right_child(node_8) node_8.set_parent(node_6) node_12._set_height(2) node_6._set_height(1) node_8._set_height(0) return node_12
def test_delete_of_a_single_root_node(self): tree = AVL(Node(10)) tree.delete(10) expect(tree.get_root()).to.equal(None)
def create_zig_zag_tree_right_left(): node_12 = Node(12) node_14 = Node(14) node_13 = Node(13) node_12.set_right_child(node_14) node_14.set_parent(node_12) node_14.set_left_child(node_13) node_13.set_parent(node_14) node_12._set_height(2) node_14._set_height(1) node_13._set_height(0) return node_12
def create_tree_for_testing_successor(): node_40 = Node(40) node_50 = Node(50) node_55 = Node(55) node_65 = Node(65) node_70 = Node(70) node_90 = Node(90) node_105 = Node(105) node_90.set_right_child(node_105) node_90.set_left_child(node_50) node_105.set_parent(node_90) node_50.set_parent(node_90) node_50.set_right_child(node_70) node_50.set_left_child(node_40) node_70.set_parent(node_50) node_40.set_parent(node_50) node_70.set_left_child(node_65) node_65.set_parent(node_70) node_65.set_left_child(node_55) node_55.set_parent(node_65) return node_90
def create_valid_avl_tree(): node_10 = Node(10) node_minus_3 = Node(-3) node_minus_20 = Node(-20) node_5 = Node(5) node_3 = Node(3) node_15 = Node(15) node_20 = Node(20) node_12 = Node(12) node_13 = Node(13) node_10.set_left_child(node_minus_3) node_10.set_right_child(node_15) node_minus_3.set_parent(node_10) node_15.set_parent(node_10) node_minus_3.set_right_child(node_5) node_minus_3.set_left_child(node_minus_20) node_5.set_parent(node_minus_3) node_minus_20.set_parent(node_minus_3) node_5.set_left_child(node_3) node_3.set_parent(node_5) node_15.set_left_child(node_12) node_15.set_right_child(node_20) node_12.set_parent(node_15) node_20.set_parent(node_15) node_12.set_right_child(node_13) node_13.set_parent(node_12) node_10._set_height(3) node_minus_3._set_height(2) node_minus_20._set_height(0) node_5._set_height(1) node_3._set_height(0) node_15._set_height(2) node_20._set_height(0) node_12._set_height(1) node_13._set_height(0) node_10.set_node_count(9) node_minus_3.set_node_count(4) node_minus_20.set_node_count(1) node_5.set_node_count(2) node_3.set_node_count(1) node_15.set_node_count(4) node_20.set_node_count(1) node_12.set_node_count(2) node_13.set_node_count(1) return node_10
def create_right_rotable_tree(): A = Node(24, name='A') B = Node(18, name='B') a = Node(16, name='a') b = Node(14, name='b') c = Node(17, name='c') A.set_right_child(c) c.set_parent(A) A.set_left_child(B) B.set_parent(A) B.set_right_child(b) B.set_left_child(a) a.set_parent(B) b.set_parent(B) A._set_height(2) B._set_height(1) a._set_height(0) b._set_height(0) c._set_height(0) return A
def create_tree_for_testing_predecessor(): node_90 = Node(90) node_50 = Node(50) node_150 = Node(150) node_160 = Node(160) node_140 = Node(140) node_144 = Node(144) node_147 = Node(147) node_90.set_right_child(node_150) node_90.set_left_child(node_50) node_150.set_parent(node_90) node_50.set_parent(node_90) node_150.set_right_child(node_160) node_150.set_left_child(node_140) node_160.set_parent(node_150) node_140.set_parent(node_150) node_140.set_right_child(node_144) node_144.set_parent(node_140) node_144.set_right_child(node_147) node_147.set_parent(node_144) return node_90
def setUp(self): self.tree = Node.from_list_raw(self.LIST)
def create_balanced_tree(): node_0 = Node(0) node_1 = Node(1) node_2 = Node(2) node_1.set_left_child(node_0) node_1.set_right_child(node_2) node_0.set_parent(node_1) node_2.set_parent(node_1) node_1._set_height(1) node_0._set_height(0) node_2._set_height(0) return node_1
def test_08_calc_bf(self): tree = Node(100) self.assertEqual(tree.calc_bf(), 0) tree.insert(50) self.assertEqual(tree.calc_bf(), 1) tree.insert(30) self.assertEqual(tree.calc_bf(), 2) tree.insert(60) self.assertEqual(tree.calc_bf(), 2) tree.insert(150) self.assertEqual(tree.calc_bf(), 1) tree.insert(170) self.assertEqual(tree.calc_bf(), 0) tree.insert(130) self.assertEqual(tree.calc_bf(), 0)
def test_10_invalid_rotation(self): tree = Node.from_list([100, 30, 20, 50]) self.assertRaises(RuntimeError, tree.search(20).rotate_ccw) self.assertRaises(RuntimeError, tree.search(50).rotate_cw)
def test_03_insert(self): tree = Node(6) for i in (4, 7, 9, 12, 1, 0, 3): tree.insert(i) self.assertEqual(tree.to_list(), self.LIST)
def create_unbalanced_tree_with_equal_weight_on_second_level(): node_5 = Node(5) node_4 = Node(4) node_2 = Node(2) node_3 = Node(3) node_5.set_left_child(node_4) node_4.set_parent(node_5) node_4.set_left_child(node_2) node_4.set_right_child(node_3) node_2.set_parent(node_4) node_3.set_parent(node_4) node_2._set_height(0) node_3._set_height(0) node_4._set_height(1) node_5._set_height(2) node_2.set_node_count(1) node_3.set_node_count(1) node_4.set_node_count(3) node_5.set_node_count(4) return node_5
class TestBalance: def build_unbalanced_tree(self, bst, node_list): for node in node_list: new_node = Node(node[0], node[1]) new_node.height = node[2] if bst.root == None: bst.root = new_node else: current_node = bst.root while current_node: if new_node.key <= current_node.key: if current_node.left_child == None: new_node.parent = current_node current_node.left_child = new_node break else: current_node = current_node.left_child else: if current_node.right_child == None: new_node.parent = current_node current_node.right_child = new_node break else: current_node = current_node.right_child return bst @pytest.mark.parametrize( 'parent_node, parent_height, left_node, left_node_height, right_node, right_node_height', [(Node(50, 'A'), 6, Node(25, 'B'), 5, Node(75, 'C'), 5), (Node(50, 'A'), 6, Node(25, 'B'), 3, Node(75, 'C'), 5), (Node(50, 'A'), 6, Node(25, 'B'), 5, Node(75, 'C'), 3), (Node(50, 'A'), 6, None, None, Node(75, 'C'), 5), (Node(50, 'A'), 6, Node(25, 'B'), 5, None, None)]) def test_update_node_height(self, parent_node, parent_height, left_node, left_node_height, right_node, right_node_height): bst = BST() if left_node: left_node.height = left_node_height if right_node: right_node.height = right_node_height parent_node.left_child = left_node parent_node.right_child = right_node bst.root = parent_node bst.update_node_height(bst.root) assert bst.root.height == parent_height @pytest.mark.parametrize('node', [(14), (96), (23), (31), (85)]) def test_update_parent_node_height(self, populated_bst, node): root_height = populated_bst.root.height assert root_height == 4 start_node = populated_bst.get(node) zero_branch_node_heights(populated_bst, start_node) assert populated_bst.root.height == 0 populated_bst.update_parent_node_heights(start_node) assert populated_bst.root.height == root_height @pytest.mark.parametrize( 'parent_node, parent_bf, left_node, left_node_height, right_node, right_node_height', [(Node(50, 'A'), 0, Node(25, 'B'), 5, Node(75, 'C'), 5), (Node(50, 'A'), 2, Node(25, 'B'), 3, Node(75, 'C'), 5), (Node(50, 'A'), 2, Node(25, 'B'), 5, Node(75, 'C'), 3), (Node(50, 'A'), 6, None, None, Node(75, 'C'), 5), (Node(50, 'A'), 6, Node(25, 'B'), 5, None, None)]) def test_update_balance_factor(self, parent_node, parent_bf, left_node, left_node_height, right_node, right_node_height): bst = BST() if left_node: left_node.height = left_node_height if right_node: right_node.height = right_node_height parent_node.left_child = left_node parent_node.right_child = right_node bst.root = parent_node assert bst.get_balance_factor(bst.root) == parent_bf @pytest.mark.parametrize( 'node_list, rebalanced_node_list', [(right_heavy_right_child_right_heavy_bst, rebalanced_right_heavy_right_child_right_heavy_node_list), (right_heavy_right_child_left_heavy_bst, rebalanced_right_heavy_right_child_left_heavy_node_list), (left_heavy_left_child_left_heavy_bst, rebalanced_left_heavy_left_child_left_heavy_node_list), (left_heavy_left_child_right_heavy_bst, rebalanced_left_heavy_left_child_right_heavy_node_list)]) def test_rebalance(self, node_list, rebalanced_node_list): # All test trees are unbalacned about root. bst = BST() self.build_unbalanced_tree(bst, node_list) bst.rebalance(bst.root) assert bst.breadth_first_traversal() == rebalanced_node_list def test_left_rotation(self): # NOTE: SHOULD COME UP WITH TEST TO TEST NON ROOT UN BALANCE # All test trees are unbalanced about root bst = BST() self.build_unbalanced_tree(bst, right_heavy_right_child_right_heavy_bst) bst.left_rotation(bst.root) print( f'lc-height: {bst.root.left_child.height}, rc-height: {bst.root.right_child.height}' ) assert bst.root.left_child.height - bst.root.right_child.height == 0 def test_right_rotation(self): # NOTE: SHOULD COME UP WITH TEST TO TEST NON ROOT UN BALANCE # All test trees are unbalanced about root bst = BST() self.build_unbalanced_tree(bst, left_heavy_left_child_left_heavy_bst) bst.right_rotation(bst.root) print( f'lc-height: {bst.root.left_child.height}, rc-height: {bst.root.right_child.height}' ) assert bst.root.left_child.height - bst.root.right_child.height == 0
def create_unbalanced_tree(): node_0 = Node(0) node_1 = Node(1) node_2 = Node(2) node_4 = Node(4) node_5 = Node(5) node_1.set_left_child(node_0) node_1.set_right_child(node_2) node_0.set_parent(node_1) node_2.set_parent(node_1) node_2.set_right_child(node_4) node_4.set_parent(node_2) node_4.set_right_child(node_5) node_5.set_parent(node_4) node_1._set_height(3) node_0._set_height(0) node_2._set_height(2) node_4._set_height(1) node_5._set_height(0) return node_1
def create_unbalanced_tree_with_zig_zag(): node_0 = Node(0) node_1 = Node(1) node_2 = Node(2) node_3 = Node(3) node_4 = Node(4) node_1.set_left_child(node_0) node_1.set_right_child(node_2) node_0.set_parent(node_1) node_2.set_parent(node_1) node_2.set_right_child(node_4) node_4.set_parent(node_2) node_4.set_left_child(node_3) node_3.set_parent(node_4) node_1._set_height(3) node_0._set_height(0) node_2._set_height(2) node_4._set_height(1) node_3._set_height(0) return (node_1, node_3)