Пример #1
0
	def test_node_balance_factor(self):
		data = [1, 2]
		avl_tree = AVLTree(data)
		assert avl_tree.root.balance_factor() == -1
		data = [2, 1]
		avl_tree = AVLTree(data)
		assert avl_tree.root.balance_factor() == 1
Пример #2
0
    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)
Пример #3
0
	def test_single_right_rotation_1(self):
		data = [3, 2, 1]
		avl_tree = AVLTree(data)
		assert avl_tree.root.data == 2
		assert avl_tree.root.left_child.data == 1
		assert avl_tree.root.right_child.data == 3
		assert avl_tree.items_level_order() == [2, 1, 3]
Пример #4
0
    def test_delete_single_element(self):
        tree = AVLTree([1])

        tree.delete(1)

        self.assertNotIn(1, tree)
        self.assertFalse(tree)
        self.assertEqual(len(tree), 0)
Пример #5
0
    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)
Пример #6
0
    def test_delete_leaf_node(self):
        tree = AVLTree([1, 2])

        tree.delete(2)

        self.assertIn(1, tree)
        self.assertNotIn(2, tree)
        self.assertTrue(tree)
        self.assertEqual(len(tree), 1)
Пример #7
0
    def test_delete_entry_make_tree_unbalanced(self):
        entries = [5, 3, 8, 2, 4, 7, 11, 1, 6, 10, 12, 9]
        tree = AVLTree(entries)
        entry_to_be_deleted = 4

        tree.delete(entry_to_be_deleted)

        expected_order = (8, 5, 11, 2, 7, 10, 12, 1, 3, 6, 9)
        self.assertNotIn(entry_to_be_deleted, tree)
        self.assertTupleEqual(tuple(tree.traverse('bfs')), expected_order)
Пример #8
0
    def test_delete_entry_but_tree_remains_balanced(self):
        entries = [10, 5, 11, 3, 7, 15]
        tree = AVLTree(entries)
        entry_to_be_deleted = 10

        tree.delete(entry_to_be_deleted)

        expected_order = (7, 5, 11, 3, 15)
        self.assertNotIn(entry_to_be_deleted, tree)
        self.assertTupleEqual(tuple(tree.traverse('bfs')), expected_order)
Пример #9
0
    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)
Пример #10
0
 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])
Пример #11
0
 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])
Пример #12
0
 def test_heightRootNodeLeftRight3LevelChildren(self):
     tree = AVLTree()
     tree.insert(4)
     tree.insert(5)
     tree.insert(2)
     tree.insert(3)
     tree.insert(1)
     height = tree.get_height(tree.root)
     self.assertEqual(height, 3)
Пример #13
0
    def test_empty_traversal(self):
        tree = AVLTree()

        d = {
            'preorder': (),
            'inorder': (),
            'postorder': (),
            'bfs': (),
        }

        for order, expected_value in d.items():
            with self.subTest(f"test {order}"):
                self.assertTupleEqual(tuple(tree.traverse(order)),
                                      expected_value)
Пример #14
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
Пример #15
0
    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)
Пример #16
0
    def test_initialize_tree_from_sequence(self):
        import math
        entries = [1, 2, 3, 4, 5, 6, 7]
        tree = AVLTree(entries)

        expected_order = (4, 2, 6, 1, 3, 5, 7)
        with self.subTest(
                f"bfs traversal must be have this order {expected_order}."):
            self.assertTupleEqual(tuple(tree.traverse('bfs')), expected_order)
        with self.subTest(f"tree must have {len(entries)} entries."):
            self.assertEqual(len(tree), len(entries))
        with self.subTest(
                f"tree must have {math.ceil(math.log2(len(entries)))} height."
        ):
            self.assertEqual(tree.height, math.ceil(math.log2(len(entries))))
Пример #17
0
def getResults():
    """
        Return search results
    """

    searchQuery = request.args.get('word')

    if not searchQuery:
        return json.dumps([])

    t = AVLTree()

    treeSearch.search(searchQuery, 3, t)

    return json.dumps(t.inorder_traverse())
Пример #18
0
    def test_search_complex_data_type(self):
        tree = AVLTree([
            Entry(1, 'a'),
            Entry(2, 'b'),
            Entry(3, 'c'),
            Entry(3, 'd'),
        ])
        entry = tree.search(Entry(3, 'd'))

        self.assertEqual(Entry(3, 'd'), entry)

        entry = Entry(3113, 'd')
        with self.assertRaises(KeyError) as context:
            tree.search(entry)
        self.assertIn(f"Entry {entry} not found.", str(context.exception))
def gen_balanced_tree(range_bounds=DEFAULT_RANGE_BOUNDS,
                      value_bounds=DEFAULT_VALUE_BOUNDS):
    """
    Generate a balanced AVLTree from random data
    """
    tree = AVLTree()
    return fill_random_tree(tree, range_bounds, value_bounds)
Пример #20
0
def test_insert_remove(
    size
):  # test tree from random, delete, and rebalance, setitem with existing key
    lbase = list(range(0, size))
    random.shuffle(lbase)  # randomize

    dref = {}
    tree = AVLTree()
    for key in lbase:
        v = random.choice(lbase)
        tree[key] = v
        dref[key] = v
        assert_true(
            dict_to_sorted_pairs(dref) == list(tree),
            f"random tree did not match reference")
        assert_true(
            is_balanced(tree),
            f"1 tree is not balanced after inserting {size} random keys/values"
        )
    assert_true(
        dict_to_sorted_pairs(dref) == list(tree),
        f"random tree did not match reference")
    deleted_keys = random.sample(lbase, size // 2)
    for key in deleted_keys:  # delete half of original
        del tree[key]
        del dref[key]
        assert_true(is_balanced(tree),
                    f"tree is not balanced after deleting key:{key} ")
        assert_true(
            dict_to_sorted_pairs(dref) == list(tree),
            f"random tree did not match reference")
 def test_balanced_tree1(self):
     """
     Test against a balanced binary tree
     """
     values = [1, 2, 3]
     tree, _ = fill_tree(AVLTree(), values)
     actual = tree_is_balanced(tree)
     self.assertTrue(actual)
Пример #22
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)
Пример #23
0
    def test_equals(self):
        tree1 = AVLTree([1, 2, 3, 4, 5])
        tree2 = AVLTree([2, 1, 4, 3, 5])
        tree3 = AVLTree([1, 2, 3, 4, 5, 6])

        with self.subTest(f"test equal trees"):
            self.assertEqual(tree1, tree2)
            self.assertFalse(tree1 is tree2)
        with self.subTest(f"test different trees"):
            self.assertNotEqual(tree1, tree3)
            self.assertFalse(tree1 is tree3)
            self.assertNotEqual(tree2, tree3)
            self.assertFalse(tree2 is tree3)
        with self.subTest(f"test tree is different from other classes"):
            self.assertNotEqual(tree1, int(9))
        with self.subTest(f"test tree is different from empty tree"):
            self.assertNotEqual(tree1, AVLTree())
Пример #24
0
 def compare_tree_expected(self, values: list):
     """
     Helper function that sorts the given list and compares the result to
     an inorder traversal of the AVL.
     """
     expected = sorted(values)
     actual = AVLTree(values).traverse()
     self.assertEqual(expected, actual)
Пример #25
0
    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)
Пример #26
0
 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])
Пример #27
0
    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)
Пример #28
0
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
Пример #29
0
 def test_insert_with_left_right_rotation(self):
     number = [10, 1, 5]
     avlTree = AVLTree(numbers)
     assert avlTree.root.number == 5
     assert avlTree.root.left.number == 1
     assert avlTree.root.left.number == 10
     
     assert avlTree.root.height = 1
     assert avlTree.root.left.height = 2
     assert avlTree.root.right.height = 2
Пример #30
0
 def test_insert_with_left_left_rotation(self):
     number = [14, 20, 16]
     avlTree = AVLTree(numbers)
     assert avlTree.root.number == 16
     assert avlTree.root.left.number == 14
     assert avlTree.root.left.number == 20
     
     assert avlTree.root.height = 1
     assert avlTree.root.left.height = 2
     assert avlTree.root.right.height = 2
Пример #31
0
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
Пример #32
0
    def process_tree(prev_info, build_first):

        for_tree_build = list()
        for_tree_build.append(get_dict(prev_info))

        prev_x1 = float(prev_info[x1i])
        ALL_XS.append([prev_x1, None])

        next_info = f.readline().split()

        if next_info:
            next_x1 = float(next_info[x1i])

            while prev_x1 == next_x1:
                for_tree_build.append(get_dict(next_info))

                next_info = f.readline().split()
                next_x1 = float(next_info[x1i])

            # середина между x(i) и x(i+1) для нахождений val-ов
            x_middle = (next_x1+prev_x1)/2

            prev_to_delete = to_delete

            # обрабатываем ноды будущего дерева
            to_add = process_tree_nodes(for_tree_build, x_middle, next_info[x1i])

            print '-'*80
            print to_add
            print prev_to_delete

            if build_first:
                tree = AVLTree()
                for n in to_add:
                    tree.add(tree.root, n['val'], n['a'], n['b'], n['pol_id'])
                tree.show()
                ref_to_tree = tree
            else:
                # если кривые координаты, идут вразброс с дырами,
                # то строим новое дерево
                #  __           __
                # /  \ пустота /  \
                # \__/         \__/

                if not prev_to_delete:
                    print 'Hole'
                    tree = AVLTree()
                    for n in to_add:
                        tree.add(tree.root, n['val'], n['a'], n['b'], n['pol_id'])

                    tree.show()
                    ref_to_tree = tree
                else:
                    prev_tree = ALL_XS[-2][1]
                    next_tree = deepcopy(prev_tree)

                    # пока грубое добавление/удаление
                    for n in to_add:
                        next_tree.add(next_tree.root, n['val'], n['a'], n['b'], n['pol_id'])
                    for n in prev_to_delete:
                        next_tree.delete(n['val'])

                    ref_to_tree = next_tree
                    next_tree.show()

            ALL_XS[-1][1] = ref_to_tree

            return next_info

        # TODO обработать последнюю строку(последний x),
        # TODO а то теряется последнее дерево

        return None
Пример #33
0
def process_tree(row, main_file, err_del_nodes_old, del_nodes_old, is_holl):

    # находим ноды для нового дерева
    row_float = float(row['x1'])
    all_x2 = [float(row['x2']), ]

    print 'STAAAAAAAAAAAAAAAAAAAAAAAAAAAAAART'
    print 'is_holl', is_holl

    try:
        next_line = main_file.next()
        next_row = get_row_dict(next_line)
        print 'next_row', next_row
        next_float = float(next_row['x1'])
    except StopIteration:
        return None, 1, 1, 1

    add_nodes = [row, ]

    while next_float == row_float:
        add_nodes.append(next_row)

        all_x2.append(float(next_row['x2']))

        try:
            next_line = main_file.next()
            next_row = get_row_dict(next_line)
            next_float = float(next_row['x1'])
        except StopIteration:
            next_float = 181
            break

    min_x2_float = min(all_x2)
    max_x2_float = max(all_x2)

    x_middle = (min_x2_float + row_float) / 2
    # print 'all_x2', all_x2
    # print 'x_middle', x_middle, 'prev_row', row_float, 'next_row', next_float
    prev_tree = ALL_XS[-1][1]

    next_tree = AVLTree()
    # l()
    # print 'prev_tree'
    # prev_tree.show()
    # l()
    print 'err_del_nodes_old', err_del_nodes_old
    l()
    print 'prev_tree'
    prev_tree.show()
    # l()
    print 'next_tree'
    next_tree.show()

    # актуализируем все значения новых нодов для добавления
    update_dict_vals(add_nodes, x_middle)

    # если предыдущее дерево пусто или между полигонами дыра
    if is_holl or prev_tree.root.val is None:
        for a in add_nodes:
            # print 'add', float(a['val'])
            next_tree.add(next_tree.root, float(a['val']), a['a'], a['b'], a['pol_id'], a['x2'], a['y2'])

    else:
        # удаляем ноды битые, у которых х2 меньше, чем следующий х1
        for err_d in err_del_nodes_old:
            print 'delete err_del_node', float(err_d['val'])
            next_tree.delete_versionly(prev_tree, float(err_d['val'])) # 45.7427962225

        print 'del_nodes_old', del_nodes_old

        # обработка нодов на замену/добавление/удаление
        to_replace, proc_del, proc_add = treatment_add_del(del_nodes_old, add_nodes)

        print 'proc_del', proc_del

        for d in proc_del:
            next_tree.delete_versionly(prev_tree, float(d['val']))

        print 'to_replace', to_replace

        for (d, a) in to_replace:
            next_tree.replace_versionly(prev_tree, float(d['val']), a)
        # актуализируем все значения нодов в дереве
        next_tree.update_vals(x_middle)
        # актуализируем все значения новых нодов для добавления
        # update_dict_vals(proc_add, x_middle)

        print 'proc_add', proc_add

        # предыдущее дерево непусто, но новое дерево пусто,
        # и если мы удаляли уже, то без версионности
        if next_tree.root.val is None and (del_nodes_old or err_del_nodes_old):
            l()
            print 'next_tree.root.val is None and (del_nodes_old or err_del_nodes_old)!!!'
            for a in proc_add:
                # print 'add', a['val']
                next_tree.add(next_tree.root, float(a['val']), a['a'], a['b'], a['pol_id'], a['x2'], a['y2'])
        # новое просто пусто(т.к. ничего не удадяли) или непусто, то версионность
        else:
            l()
            print 'next_tree.root.val is None or is not empty!!!'
            for a in proc_add:
                # print 'add_versionly', a['val']
                next_tree.add_versionly(prev_tree, a)

    # обнуляем версионность дерева next_tree
    next_tree.remove_update_flags(next_tree.root)

    ALL_XS.append([float(row_float), next_tree])

    err_del_nodes = [node for node in add_nodes if float(node['x2']) < next_float]
    print 'err_del_nodes', err_del_nodes
    # if err_del_nodes:
    #     print 'Err_del_nodes exists', row_float, err_del_nodes
    del_nodes = [node for node in add_nodes if float(node['x2']) == next_float]

    print 'next_tree'
    next_tree.show()

    print 'EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEND'
    print 'max_x2_float', max_x2_float, 'next_float', next_float
    l()

    return next_row, err_del_nodes, del_nodes, max_x2_float < next_float
Пример #34
0
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