def test_delete_sanity_when_deleting_everything_from_builded_key_except_from_one_element( del_all_but): asa = ASA() for i in range(7): asa.insert(i) delete = [i for i in range(7) if i != del_all_but] for dd in delete: asa.delete(dd) assert len(asa.root.keys) == 1 assert asa.root.keys == [del_all_but] assert asa.root.children == []
def test_delete_should_handle_filing_empty_leaf_for_one_level_tree_and_two_children( add, delete, empty_value, ch_index): asa = ASA() for i in range(3): asa.insert(i) asa.insert(add) assert asa.delete(delete) modified_node = asa.root.children[ch_index] assert empty_value == modified_node.keys[0].key # check if structure is preserved parent = modified_node.parent root = asa.root assert parent == root assert len(parent.keys) == 1 p_keys = parent.keys ch_1, ch_2 = parent.children assert ch_1.keys[0].key < p_keys[0].key < ch_2.keys[0].key assert ch_1.keys[0].key < ch_2.keys[0].key assert len(ch_1.keys) == len(ch_2.keys) == 1
def test_should_rebalance_when_one_of_sibling_nodes_for_two_level_tree_with_single_key_root_node( to_add, to_delete, insertion_order): asa = ASA() for i in range(7): asa.insert(i) for el in to_add: asa.insert(el) assert asa.delete(to_delete) def check_structure(root_1, root_2): assert root_1.keys == root_2.keys assert len(root_1.children) == len(root_2.children) for ch_1, ch_2 in zip(root_1.children, root_2.children): check_structure(ch_1, ch_2) # integrity check build tree without deleted element elements = list(range(7)) + to_add elements.remove(to_delete) elements.sort() asa_after_delete = ASA() for el in insertion_order: asa_after_delete.insert(el) check_structure(asa.root, asa_after_delete.root)
def test_should_delete_empty_leaf_when_parent_got_two_elements( delete_key, parent_key, ch_index): asa = ASA() for i in range(5): asa.insert(i) assert asa.delete(delete_key) # check if structure is preserved values = [i for i in range(5) if i != delete_key] asa_values = [el.key for el in asa.sorted_d_queue] assert values == asa_values _, parent = asa.search(parent_key) assert parent == asa.root assert len(parent.keys) == 1 p_keys = parent.keys ch_1, ch_2 = parent.children assert ch_1.keys[0].key < p_keys[0].key < ch_2.keys[0].key assert ch_1.keys[0].key < ch_2.keys[0].key child_with_two_keys = parent.children[ch_index] assert len(child_with_two_keys.keys) == 2 assert len(parent.children[int(bool(1 - ch_index))].keys) == 1
def test_delete_should_work_for_existing_duplicated_key( elements, delete_key, count): asa = ASA() for key in elements: asa.insert(key) del_key, _ = asa.search(delete_key) assert asa.delete(delete_key) assert del_key.count == count
def draw_successive_deletion(self, starting_inserts, consecutive_deletions, name='deletion'): asa = ASA() for el in starting_inserts: asa.insert(el) save_kwargs = { "format": "GIF", "save_all": True, "duration": 1000, "loop": False, } img = self.draw_asa(asa, save=False) evolution = [img] deleted = [] for key in consecutive_deletions: asa.delete(key) img = self.draw_asa(asa, save=False) draw = ImageDraw.Draw(img) a_font = ImageFont.truetype(self.font_path, 30) draw.text((30, 20), f'Start: {list(starting_inserts)}', fill='black', font=a_font) a_font = ImageFont.truetype(self.font_path, 30) draw.text((30, 50), f'Deleted: {deleted}', fill='black', font=a_font) el_font = ImageFont.truetype(self.font_path, 50) draw.text((50, 120), f'Current {key}', fill='red', font=el_font) evolution.append(img) deleted.append(key) evolution[0].save(f'{name}.gif', append_images=evolution[1:], **save_kwargs)
def test_asa_delete_should_handle_recursive_rebalancing( to_delete, root_keys, insertion_order): asa = ASA() for i in range(15): asa.insert(i) assert asa.delete(to_delete) assert asa.root.keys == root_keys asa_after_delete = ASA() for el in insertion_order: asa_after_delete.insert(el) check_structure(asa.root, asa_after_delete.root)
def test_should_replace_root_when_tree_will_shrink(to_delete, root_keys, insertion_order): asa = ASA() for i in range(7): asa.insert(i) assert asa.delete(to_delete) assert asa.root.keys == root_keys asa_after_delete = ASA() for el in insertion_order: asa_after_delete.insert(el) check_structure(asa.root, asa_after_delete.root)
def test_delete_should_handle_deleting_non_leaf_in_one_level_tree_case( elem, node_elem): asa = ASA() for i in range(3): asa.insert(i) asa.insert(elem) _, node = asa.search(node_elem) assert len(node.keys) == 2 assert asa.delete(1) assert elem in asa.root.keys elem, node = asa.search(node_elem) assert len(node.keys) == 1
def test_delete_should_replace_deleted_node_key_with_leaf_key_when_proper_leaf_key_found( elem, node_elem): asa = ASA() for i in range(13): asa.insert(i) # this will be predecessor or successor of 7 asa.insert(elem) _, node = asa.search(node_elem) assert len(node.keys) == 2 assert asa.delete(7) assert elem in asa.root.keys elem, node = asa.search(node_elem) assert len(node.keys) == 1
def test_should_colapse_structure_when_parent_has_one_hey_and_sibling_also_has_only_one_key( delete_key, parent_key): asa = ASA() for i in range(3): asa.insert(i) assert asa.delete(delete_key) # check if structure is preserved values = [i for i in range(3) if i != delete_key] asa_values = [el.key for el in asa.sorted_d_queue] assert values == asa_values _, parent = asa.search(parent_key) assert asa.root == parent assert len(parent.keys) == 2 assert parent.children == []
def test_delete_should_remove_key_from_node_with_two_keys_without_rebalancing_v2( ): asa = ASA() for i in [2, 3, 5, 7, 8, 9, 10, 11]: asa.insert(i) assert asa.delete(10) found, node = asa.search(10) assert found is False and node is None assert [e.key for e in asa.sorted_d_queue] == [2, 3, 5, 7, 8, 9, 11] found, node = asa.search(11) assert found assert node.parent.keys == [9] assert node.leaf is True
def test_should_rebalance_when_one_of_sibling_in_three_children_parent_got_two_keys( to_add, to_delete, insertion_order): asa = ASA() for i in range(11): asa.insert(i) for el in to_add: asa.insert(el) assert asa.delete(to_delete) # integrity check build tree without deleted element elements = list(range(7)) + to_add elements.remove(to_delete) elements.sort() asa_after_delete = ASA() for el in insertion_order: asa_after_delete.insert(el) check_structure(asa.root, asa_after_delete.root)
def test_delete_should_return_false_if_key_for_delete_not_found(): asa = ASA() for i in [1, 2, 2, 3, 3, 4, 4]: asa.insert(i) assert asa.delete(10) is False
def test_delete_for_initial_case(): asa = ASA() assert asa.delete(1) is False