def test_height(self): tree = AVLTree() tree.insert(9) root = tree.root self.assertEqual(root.height, 1) tree.insert(4) self.assertEqual(root.height, 2) self.assertEqual(root.left.height, 1) tree.insert(14) self.assertEqual(root.height, 2) self.assertEqual(root.left.height, 1) self.assertEqual(root.right.height, 1) tree.insert(17) self.assertEqual(root.height, 3) self.assertEqual(root.left.height, 1) self.assertEqual(root.right.height, 2) self.assertEqual(root.right.right.height, 1) tree.insert(7) self.assertEqual(root.height, 3) self.assertEqual(root.left.height, 2) self.assertEqual(root.left.right.height, 1)
def test_greater_entry_on_the_right_of_root(self): tree = AVLTree() tree.insert(9) tree.insert(14) self.assertEqual(tree.root.entry, 9) self.assertEqual(tree.root.right.entry, 14)
def test_smaller_entry_on_the_left_of_root(self): tree = AVLTree() tree.insert(9) tree.insert(4) self.assertEqual(tree.root.entry, 9) self.assertEqual(tree.root.left.entry, 4)
def test_insertPreOrderWithRootAndLeftRightNodes(self): tree = AVLTree() tree.insert(4) tree.insert(3) tree.insert(5) nodes = tree.preorder_traversal() self.assertEqual(nodes, [4, 3, 5])
def test_insertPreOrderCheckTypeErrorRaised(self): tree = AVLTree() tree.insert('a') try: tree.insert(4) except TypeError: return True
def test_balance_factor(self): tree = AVLTree() tree.insert(9) root = tree.root self.assertEqual(root.balance_factor, 0) tree.insert(4) self.assertEqual(root.balance_factor, 1) self.assertEqual(root.left.balance_factor, 0) tree.insert(14) self.assertEqual(root.balance_factor, 0) self.assertEqual(root.left.balance_factor, 0) self.assertEqual(root.right.balance_factor, 0) tree.insert(17) self.assertEqual(root.balance_factor, -1) self.assertEqual(root.left.balance_factor, 0) self.assertEqual(root.right.balance_factor, -1) self.assertEqual(root.right.right.balance_factor, 0) tree.insert(7) self.assertEqual(root.balance_factor, 0) self.assertEqual(root.left.balance_factor, -1) self.assertEqual(root.left.right.balance_factor, 0)
def test_heightRootNodeLeftRightChildren(self): tree = AVLTree() tree.insert(4) tree.insert(3) tree.insert(5) height = tree.get_height(tree.root) self.assertEqual(height, 2)
def test_avl_insertion(): """Tests that avl insertion maintains balance""" bintree = AVLTree() for i in xrange(100): bintree.insert(random.randint(0, 1e6)) assert bintree.size() == 100 assert abs(bintree.balance()) < 2 assert bintree.depth() < 9 # 2 ** 7 is 128, it should fit
def test_insert_on_empty_tree(self): tree = AVLTree() tree.insert(9) self.assertEqual(tree.root.entry, 9) self.assertEqual(tree.root.left.balance_factor, 0) self.assertEqual(tree.root.right.balance_factor, 0) self.assertTrue(tree)
def test_rightRotationOnRoot(self): tree = AVLTree() tree.insert(3) tree.insert(2) tree.insert(1) tree.root = tree.right_rotation(tree.root) nodes = tree.preorder_traversal() self.assertEqual(nodes, [2, 1, 3])
def test_length(self): tree = AVLTree() entries = range(150) for entry in entries: tree.insert(entry) with self.subTest("test non-empty tree"): self.assertEqual(len(tree), len(entries)) with self.subTest("test empty tree"): self.assertEqual(len(AVLTree()), 0)
def test_node_update_height(self): data = [1, 2] avl_tree = AVLTree(data) assert avl_tree.root.data == 1 assert avl_tree.root.height == 1 assert avl_tree.root.left_child == None assert avl_tree.root.right_child.height == 0 avl_tree.insert(3) assert avl_tree.root.data == 2 assert avl_tree.root.height == 1 assert avl_tree.root.left_child.data == 1 assert avl_tree.root.left_child.height == 0 assert avl_tree.root.right_child.data == 3 assert avl_tree.root.right_child.height == 0
def build_avl(alist): avl_tree = AVLTree() #line by line splits in order to check if the word starts with an alpha char or not for i in range(len(alist)): temp_a = alist[i].split(" ") temp_w = temp_a[0] #if it is an alpha char it will create a new list for the embedding and create a node if temp_w.isalpha(): embedding = [] for j in range(len(temp_a - 1)): embedding.append(temp_a[j + 1]) temp_n = Node(temp_w, embedding) avl_tree.insert(temp_n)
def test_contains(self): with self.subTest("test empty tree should not contain any entry"): self.assertNotIn(10, AVLTree()) with self.subTest("test single element must be in tree"): tree = AVLTree() tree.insert(10) self.assertIn(10, tree) with self.subTest("test element must be in tree"): entries = range(128) tree = AVLTree() for entry in entries: tree.insert(entry) for entry in entries: self.assertIn(entry, tree)
def test_right_left_rotation(self): tree = AVLTree() tree.insert(1) root = tree.root self.assertEqual(root.balance_factor, 0) self.assertEqual(root.height, 1) self.assertEqual(root.entry, 1) tree.insert(3) root = tree.root self.assertEqual(root.balance_factor, -1) self.assertEqual(root.height, 2) self.assertEqual(root.entry, 1) self.assertEqual(root.right.entry, 3) tree.insert(2) root = tree.root self.assertEqual(root.balance_factor, 0) self.assertEqual(root.left.balance_factor, 0) self.assertEqual(root.right.balance_factor, 0) self.assertEqual(root.height, 2) self.assertEqual(root.entry, 2) self.assertEqual(root.left.entry, 1) self.assertEqual(root.right.entry, 3)
def test_balanced_tree_must_have_height_of_log2(self): import math base = 2 for exp in range(2, 13): tree1 = AVLTree() tree2 = AVLTree() tree3 = AVLTree() entries = [i for i in range(base**exp)] for entry in entries: tree1.insert(entry) if entry == 0: continue tree2.insert(entry) if entry == 1: continue tree3.insert(entry) with self.subTest(f"test inserting {len(entries)} elements."): self.assertEqual(tree1.height, int(math.log2(len(entries))) + 1) self.assertEqual(len(tree1), len(entries)) with self.subTest(f"test inserting {len(entries)-1} elements."): self.assertEqual(tree2.height, int(math.log2(len(entries)))) self.assertEqual(len(tree2), len(entries) - 1) with self.subTest(f"test inserting {len(entries)-2} elements."): self.assertEqual(tree3.height, int(math.log2(len(entries)))) self.assertEqual(len(tree3), len(entries) - 2)
def test_insertPreOrderWithRootAndLeftRightNodesWithLevel1Children(self): tree = AVLTree() tree.insert(4) tree.insert(3) tree.insert(1) tree.insert(2) tree.insert(5) nodes = tree.preorder_traversal() self.assertEqual(nodes, [4, 3, 1, 2, 5])
def test_insert_duplicated_entry(self): tree = AVLTree() tree.insert(9) tree.insert(10) tree.insert(9) self.assertEqual(tree.root.entry, 9) self.assertEqual(tree.root.right.entry, 10) self.assertEqual(tree.height, 2) self.assertTrue(tree)
def test_recursive_insertion(self): tree = AVLTree() tree.insert(9) tree.insert(4) tree.insert(14) tree.insert(17) tree.insert(7) root = tree.root self.assertEqual(root.entry, 9) self.assertEqual(root.left.entry, 4) self.assertEqual(root.right.entry, 14) self.assertEqual(root.right.right.entry, 17) self.assertEqual(root.left.right.entry, 7)
class EventQueue: """ Implemented as AVLTree instead of MinHeap. """ def __init__(self): self.tree = AVLTree() self.size = 0 def insert_event(self, event: Point) -> bool: res = self.tree.insert(event) if res: self.size += 1 return res def get_nearest_event(self) -> Optional[Point]: return self.tree.min() def remove_event(self, event: Point) -> bool: res = self.tree.delete(event) if res: self.size -= 1 return res
def test_traversal(self): tree = AVLTree() tree.insert(20) tree.insert(10) tree.insert(25) tree.insert(23) tree.insert(29) tree.insert(30) d = { 'preorder': (25, 20, 10, 23, 29, 30), 'inorder': (10, 20, 23, 25, 29, 30), 'postorder': (10, 23, 20, 30, 29, 25), 'bfs': (25, 20, 29, 10, 23, 30), } for order, expected_value in d.items(): with self.subTest(f"test {order}"): self.assertTupleEqual(tuple(tree.traverse(order)), expected_value)
class AVLTreeTests(unittest.TestCase): def setUp(self): self.tree = AVLTree() def test_update_height(self): self.assertEqual(self.tree.height, -1) self.tree.node = Node(5) self.tree.update_height() self.assertEqual(self.tree.height, 0) self.tree.node.left = AVLTree(Node(3)) self.tree.update_height() self.assertEqual(self.tree.node.left.height, 0) self.assertEqual(self.tree.height, 1) self.tree.node.right = AVLTree(Node(6)) self.tree.update_height() self.assertEqual(self.tree.height, 1) self.tree.node.right.node.right = AVLTree(Node(8)) self.tree.update_height() self.assertEqual(self.tree.height, 2) def test_left_rotation(self): self.tree.node = Node(5) self.tree.node.left = AVLTree(Node('x')) self.tree.node.right = AVLTree(Node(8)) self.tree.node.right.node.left = AVLTree(Node('c')) self.tree.node.right.node.right = AVLTree(Node(9)) self.tree.node.right.node.right.node.left = AVLTree(Node('y')) self.tree.node.right.node.right.node.right = AVLTree(Node('z')) self.tree.left_rotate() self.assertEqual(self.tree.node.key, 8) self.assertEqual(self.tree.node.left.node.key, 5) self.assertEqual(self.tree.node.right.node.key, 9) self.assertEqual(self.tree.node.left.node.left.node.key, 'x') self.assertEqual(self.tree.node.left.node.right.node.key, 'c') self.assertEqual(self.tree.node.right.node.left.node.key, 'y') self.assertEqual(self.tree.node.right.node.right.node.key, 'z') def test_right_rotation(self): self.tree.node = Node(5) self.tree.node.right = AVLTree(Node('x')) self.tree.node.left = AVLTree(Node(4)) self.tree.node.left.node.right = AVLTree(Node('c')) self.tree.node.left.node.left = AVLTree(Node(3)) self.tree.node.left.node.left.node.left = AVLTree(Node('y')) self.tree.node.left.node.left.node.right = AVLTree(Node('z')) self.tree.right_rotate() self.assertEqual(self.tree.node.key, 4) self.assertEqual(self.tree.node.left.node.key, 3) self.assertEqual(self.tree.node.right.node.key, 5) self.assertEqual(self.tree.node.left.node.left.node.key, 'y') self.assertEqual(self.tree.node.left.node.right.node.key, 'z') self.assertEqual(self.tree.node.right.node.left.node.key, 'c') self.assertEqual(self.tree.node.right.node.right.node.key, 'x') def test_rebalancing(self): self.tree.node = Node(5) self.tree.node.right = AVLTree(Node('x')) self.tree.node.left = AVLTree(Node(3)) self.tree.node.left.node.right = AVLTree(Node(4)) self.tree.node.left.node.left = AVLTree(Node('c')) self.tree.node.left.node.right.node.left = AVLTree(Node('y')) self.tree.node.left.node.right.node.right = AVLTree(Node('z')) self.tree.rebalance() self.assertEqual(self.tree.node.key, 4) self.assertEqual(self.tree.node.left.node.key, 3) self.assertEqual(self.tree.node.right.node.key, 5) self.assertEqual(self.tree.node.left.node.left.node.key, 'c') self.assertEqual(self.tree.node.left.node.right.node.key, 'y') self.assertEqual(self.tree.node.right.node.left.node.key, 'z') self.assertEqual(self.tree.node.right.node.right.node.key, 'x') def test_insertion(self): self.tree.insert(5) self.assertEqual(self.tree.node.key, 5) self.tree.insert(3) self.assertEqual(self.tree.node.left.node.key, 3) self.tree.insert(6) self.assertEqual(self.tree.node.right.node.key, 6) self.tree.insert(7) self.assertEqual(self.tree.node.right.node.right.node.key, 7) self.tree.insert(8) self.assertEqual(self.tree.node.right.node.key, 7) self.assertEqual(self.tree.node.right.node.left.node.key, 6) self.assertEqual(self.tree.node.right.node.right.node.key, 8)
class SweepLineStatus: """ Implemented with AVLTree. """ def __init__(self): self.tree = AVLTree() self.size = 0 def add_segment(self, segment: Segment) -> bool: res = self.tree.insert(segment) if res: self.size += 1 return res def remove_segment(self, segment: Segment) -> bool: res = self.tree.delete(segment) if res: self.size -= 1 return res def get_above_neighbor(self, segment: Segment) -> Optional[Segment]: current = self.tree.find(segment) assert (current is not None) above = self.tree.successor(current) if above is not None: return above.key return None def get_below_neighbor(self, segment: Segment) -> Optional[Segment]: current = self.tree.find(segment) assert (current is not None) below = self.tree.predecessor(current) if below is not None: return below.key return below def intersection_with_upper(self, segment: Segment) -> Optional[Point]: current = self.tree.find(segment) assert (current is not None) # Successor, because upper's y coordinate is bigger upper = self.tree.successor(current) if upper is None: return None else: point = calculate_intersection_point(upper.key, segment) if point is None: return None return point def intersection_with_lower(self, segment: Segment) -> Optional[Point]: current = self.tree.find(segment) assert (current is not None) lower = self.tree.predecessor(current) if lower is None: return None else: point = calculate_intersection_point(lower.key, segment) if point is None: return None return point def reach_intersection_of(self, upper: Segment, lower: Segment): upper_node = self.tree.find(upper) lower_node = self.tree.find(lower) temp_key = upper_node.key upper_node.key = lower_node.key lower_node.key = temp_key
def test_heightRootNode(self): tree = AVLTree() tree.insert(4) height = tree.get_height(tree.root) self.assertEqual(height, 1)
from avl_tree import AVLTree tree = AVLTree() for i in range(0,14): tree.insert(i) tree.delete(12) print(tree.to_string())
def test_rotations(): """Tests my rotations, balance, and depth with a simple AVLtree""" # Initialization etc. should work fine, just inherits from well-tested BST bintree = AVLTree() assert bintree.depth() == 0 with pytest.raises(ValueError): bintree._rotate_left() bintree.insert(5) assert bintree.depth() == 1 with pytest.raises(ValueError): bintree._rotate_left() with pytest.raises(ValueError): bintree._rotate_right() bintree.insert(3) assert bintree.depth() == 2 with pytest.raises(ValueError): bintree._rotate_right() # 3 is on left bintree._rotate_left() # 3 now head bintree._rotate_right() # 5 is head again bintree.insert(7) bintree.insert(6) bintree.insert(2) bintree.insert(4) bintree.insert(1) bintree.insert(9) bintree.insert(10) # All in order, no rotations done # 5 # / \ # 3 7 # /\ / \ # 2 4 6 9 # | | # 1 10 bintree._rotate_right() # 7 # / \ # 5 9 # | \ \ # 3 6 10 # /\ # 2 4 # | # 1 assert bintree.value == 7 assert bintree.balance() == 2 assert bintree.size() == 9 assert bintree.depth() == 5 assert bintree.rightchild.value == 9 assert bintree.leftchild.value == 5 assert bintree.leftchild.rightchild.value == 6 bintree.leftchild._rotate_left() # Note that this breaks stuff at head; the update of depth/_level is part # of insert()/delete(), so 7 never gets releveled without the next line bintree._relevel() # 7 # / \ # 3 9 # | \ \ # 2 5 10 # / / \ # 1 4 6 assert bintree.balance() == 1 assert bintree.depth() == 4 pivot_node = bintree.leftchild assert pivot_node.value == 3 assert pivot_node.leftchild.value == 2 assert pivot_node.rightchild.value == 5
def test_avl_deletion(): """Tests that avl deletion maintains balance""" bintree = AVLTree() bintree.insert(10) bintree.insert(5) bintree.insert(15) bintree.insert(2) bintree.insert(7) bintree.insert(12) bintree.insert(30) bintree.insert(1) bintree.insert(11) bintree.insert(13) bintree.insert(35) bintree.insert(14) # 10 # / \ # 5 15 # / \ / \ # 2 7 12 30 # / / \ \ # 1 11 13 35 # \ # 14 # All inserted in an order such that no rotations occurred assert bintree.depth() == 5 assert bintree.balance() == -1 assert bintree.size() == 12 bintree.delete(15) # 10 # / \ # 5 14 # / \ / \ # 2 7 12 30 # / / \ \ # 1 11 13 35 # This is standard deletion, still in balance. # check that balance/depth update correctly assert bintree.balance() == 0 assert bintree.depth() == 4 assert bintree.size() == 11 assert bintree.rightchild.depth() == 3 assert bintree.rightchild.leftchild.depth() == 2 assert bintree.rightchild.leftchild.balance() == 0 # used to be -1 bintree.delete(7) # 10 # / \ # 5 14 # / / \ # 2 12 30 # / / \ \ # 1 11 13 35 # Now 5 is out of balance, rotate left up # 10 # / \ # 2 14 # / \ / \ # 1 5 12 30 # / \ \ # 11 13 35 assert bintree.leftchild.value == 2 assert bintree.balance() == -1 assert bintree.depth() == 4 assert bintree.leftchild.depth() == 2 assert bintree.leftchild.rightchild.depth() == 1 bintree.delete(10) # 11 # / \ # 2 14 # / \ / \ # 1 5 12 30 # \ \ # 13 35 # Just normal deletion bintree.delete(11) # 12 # / \ # 2 14 # / \ / \ # 1 5 13 30 # \ # 35 # Just normal deletion bintree.delete(12) # 13 # / \ # 2 14 # / \ \ # 1 5 30 # \ # 35 # Now 14 is out of balance, rotate 30 up # 13 # / \ # 2 30 # / \ / \ # 1 5 14 35 assert bintree.depth() == 3 assert bintree.balance() == 0 assert bintree.value == 13 assert bintree.leftchild.value == 2 assert bintree.rightchild.value == 30 assert bintree.leftchild.depth() == 2 assert bintree.rightchild.depth() == 2
def test_advanced_left_rotation(self): tree = AVLTree() tree.insert(20) root = tree.root self.assertEqual(root.balance_factor, 0) self.assertEqual(root.height, 1) self.assertEqual(root.entry, 20) tree.insert(10) root = tree.root self.assertEqual(root.balance_factor, 1) self.assertEqual(root.height, 2) self.assertEqual(root.entry, 20) self.assertEqual(root.left.entry, 10) tree.insert(25) root = tree.root self.assertEqual(root.balance_factor, 0) self.assertEqual(root.height, 2) self.assertEqual(root.entry, 20) self.assertEqual(root.right.entry, 25) tree.insert(23) root = tree.root self.assertEqual(root.balance_factor, -1) self.assertEqual(root.height, 3) self.assertEqual(root.entry, 20) self.assertEqual(root.right.left.entry, 23) tree.insert(29) root = tree.root self.assertEqual(root.balance_factor, -1) self.assertEqual(root.height, 3) self.assertEqual(root.entry, 20) self.assertEqual(root.right.right.entry, 29) tree.insert(30) root = tree.root self.assertEqual(root.balance_factor, 0) self.assertEqual(root.height, 3) self.assertEqual(root.entry, 25) self.assertEqual(root.left.entry, 20) self.assertEqual(root.right.entry, 29) self.assertEqual(root.left.left.entry, 10) self.assertEqual(root.right.right.entry, 30) self.assertEqual(root.left.right.entry, 23)
def test_advanced_right_rotation(self): tree = AVLTree() tree.insert(8) root = tree.root self.assertEqual(root.balance_factor, 0) self.assertEqual(root.height, 1) self.assertEqual(root.entry, 8) tree.insert(5) root = tree.root self.assertEqual(root.balance_factor, 1) self.assertEqual(root.height, 2) self.assertEqual(root.entry, 8) self.assertEqual(root.left.entry, 5) tree.insert(11) root = tree.root self.assertEqual(root.balance_factor, 0) self.assertEqual(root.height, 2) self.assertEqual(root.entry, 8) self.assertEqual(root.right.entry, 11) tree.insert(4) root = tree.root self.assertEqual(root.balance_factor, 1) self.assertEqual(root.height, 3) self.assertEqual(root.entry, 8) self.assertEqual(root.left.left.entry, 4) tree.insert(7) root = tree.root self.assertEqual(root.balance_factor, 1) self.assertEqual(root.height, 3) self.assertEqual(root.entry, 8) self.assertEqual(root.left.right.entry, 7) tree.insert(2) root = tree.root self.assertEqual(root.balance_factor, 0) self.assertEqual(root.height, 3) self.assertEqual(root.entry, 5) self.assertEqual(root.left.entry, 4) self.assertEqual(root.right.entry, 8) self.assertEqual(root.left.left.entry, 2) self.assertEqual(root.right.right.entry, 11) self.assertEqual(root.right.left.entry, 7)
def test_insertPreOrderTreeWithRootLetter(self): tree = AVLTree() tree.insert('a') nodes = tree.preorder_traversal() self.assertEqual(nodes, ['a'])