diff --git a/__main__.py b/__main__.py index 9cbaa697cd953cac9f13ab45c33fdbda57106656..841342aa8bba93663032eb41f83db776d3445b4f 100644 --- a/__main__.py +++ b/__main__.py @@ -58,6 +58,12 @@ def array_insert_sorted(array, value): return index +def sorted_array_delete(array, value): + index = find_value_index_in_array(array, value) + array.pop(index) + return index + + # B+ Tree : START @@ -226,108 +232,113 @@ def bptree_delete_internal(root, parents, node, key): parent = parents.pop() if len(node.keys) < node.order and node != root: - children_index = None + print("Merge 2") + # children_index = None + + # for i, child in enumerate(parent.children): + # if node == child: + # children_index = i + + # if children_index == 0: + # sibling = parent.children[children_index + 1] + # parent_key = parent.keys[children_index] + # parent.keys.pop(find_value_index_in_array(parent.keys, parent_key)) + # array_insert_sorted(sibling.keys, parent_key) + # array_insert_sorted(sibling.keys, node.keys[0]) + # sibling.children = node.children + sibling.children + # else: + # sibling = parent.children[children_index - 1] + # parent_key = parent.keys[children_index - 1] + # parent.keys.pop(find_value_index_in_array(parent.keys, parent_key)) + # array_insert_sorted(node.keys, parent_key) + + # for key in sibling.keys: + # array_insert_sorted(node.keys, key) + + # node.children = sibling.children + node.children + + # if parent == root and len(parent.keys) == 0: + # bptree_shrink(root) + + if is_value_in_array(node.keys, key) and len(node.children) > 0: + index = find_value_index_in_array(node.keys, key) + node.keys[index] = bptree_find_smallest_key(node.children[index + 1]) - for i, child in enumerate(parent.children): - if node == child: - children_index = i + if node != root: + bptree_delete_internal(root, parents, parent, key) - if children_index == 0: + +def bptree_find_sibling(parent, children_index): + if children_index == 0: + # Must take the sibling on the right. + sibling = parent.children[1] + sibling_position = "r" + elif children_index == 2 * parent.order - 1: + # Must take the sibling on the left. + sibling = parent.children[2 * parent.order - 2] + sibling_position = "l" + else: + # Can take the sibling from left or right. + if len(parent.children[children_index - 1].keys) > parent.order: + # The left sibling has enough keys to borrow one. + sibling = parent.children[children_index - 1] + sibling_position = "l" + elif len(parent.children[children_index + 1].keys) > parent.order: + # The right sibling has enough keys to borrow one. sibling = parent.children[children_index + 1] - parent_key = parent.keys[children_index] - parent.keys.pop(find_value_index_in_array(parent.keys, parent_key)) - array_insert_sorted(sibling.keys, parent_key) - array_insert_sorted(sibling.keys, node.keys[0]) - sibling.children = node.children + sibling.children + sibling_position = "r" else: + # A merge between the node and the left sibling is required. sibling = parent.children[children_index - 1] - parent_key = parent.keys[children_index - 1] - parent.keys.pop(find_value_index_in_array(parent.keys, parent_key)) - array_insert_sorted(node.keys, parent_key) - - for key in sibling.keys: - array_insert_sorted(node.keys, key) - node.children = sibling.children + node.children - - if parent == root and len(parent.keys) == 0: - bptree_shrink(root) - - if is_value_in_array(node.keys, key): - index = find_value_index_in_array(node.keys, key) - node.keys[index] = bptree_find_smallest_key(node.children[index + 1]) - - if node != root: - bptree_delete_internal(root, parents, parent, key) + return sibling, sibling_position def bptree_delete_leaf(root, parents, leaf, key): + if leaf != root: + parent = parents.pop() + if len(leaf.keys) > leaf.order or leaf == root: - deletion_index = find_value_index_in_array(leaf.keys, key) - leaf.keys.pop(deletion_index) - bptree_delete_internal(root, parents, parents.pop(), key) + sorted_array_delete(leaf.keys, key) else: deletion_index = find_value_index_in_array(leaf.keys, key) leaf.keys.pop(deletion_index) - parent = parents.pop() children_index = None for i, child in enumerate(parent.children): if leaf == child: children_index = i - if children_index == 0: - # Must take the sibling on the right. - sibling = parent.children[1] - sibling_position = "r" - elif children_index == 2 * leaf.order - 1: - # Must take the sibling on the left. - sibling = parent.children[children_index - 1] - sibling_position = "l" - else: - # Can take the sibling from left or right. - if len(parent.children[children_index - 1].keys) > leaf.order: - # The left sibling has enough keys to borrow one. - sibling = parent.children[children_index - 1] - sibling_position = "l" - elif len(parent.children[children_index + 1].keys) > leaf.order: - # The right sibling has enough keys to borrow one. - sibling = parent.children[children_index + 1] - sibling_position = "r" - else: - # A merge between the node and the left sibling is required. - sibling = parent.children[children_index - 1] + sibling, sibling_position = bptree_find_sibling(parent, children_index) if len(sibling.keys) == sibling.order: - if children_index == 0: - # Sibling not on the left. - array_insert_sorted(sibling.keys, leaf.keys[0]) - parent.children.pop(children_index) - parent.keys.pop(children_index) - else: - for key in sibling.keys: - array_insert_sorted(leaf.keys, key) - - parent.children.pop(children_index - 1) - parent.keys.pop(children_index - 1) - - bptree_delete_internal(root, parents, parent, key) + print("Merge 1") + pass + # if children_index == 0: + # # Sibling not on the left. + # array_insert_sorted(sibling.keys, leaf.keys[0]) + # parent.children.pop(children_index) + # parent.keys.pop(children_index) + # else: + # for key in sibling.keys: + # array_insert_sorted(leaf.keys, key) + + # parent.children.pop(children_index - 1) + # parent.keys.pop(children_index - 1) else: if sibling_position == "l": sibling_key = sibling.keys[len(sibling.keys) - 1] - deletion_index = find_value_index_in_array(sibling.keys, sibling_key) - sibling.keys.pop(deletion_index) + sorted_array_delete(sibling.keys, sibling_key) array_insert_sorted(leaf.keys, sibling_key) parent.keys[children_index - 1] = sibling_key else: sibling_key = sibling.keys[0] - deletion_index = find_value_index_in_array(sibling.keys, sibling_key) - sibling.keys.pop(deletion_index) + sorted_array_delete(sibling.keys, sibling_key) array_insert_sorted(leaf.keys, sibling_key) parent.keys[children_index] = sibling.keys[0] - bptree_delete_internal(root, parents, parent, key) + bptree_delete_internal(root, parents, parent, key) def deletion_find_leaf(root, key): @@ -420,48 +431,44 @@ def main(): random.seed(a) order = 2 - root = Node(order) - keys = generate_random_keys(40, 1, 99) - print(keys) + # root = Node(order) + # keys = generate_random_keys(40, 1, 99) + # print(keys) - for key in keys: - bptree_insert(root, key) + # for key in keys: + # bptree_insert(root, key) - bptree_print(root) - extracted_keys = bptree_extract_all_keys(root) - assert extracted_keys == sorted(keys) + # bptree_print(root) + # extracted_keys = bptree_extract_all_keys(root) + # assert extracted_keys == sorted(keys) - for key in keys: - assert bptree_search(root, key) + # for key in keys: + # assert bptree_search(root, key) - for _ in range(5): - while True: - random_key = random.randint(1, 99) + # for _ in range(5): + # while True: + # random_key = random.randint(1, 99) - if random_key not in keys: - break + # if random_key not in keys: + # break - assert not bptree_search(root, random_key) + # assert not bptree_search(root, random_key) - # root = Node(order) - # keys = generate_random_keys(18, 1, 99) - # print(keys) - # print("=====") + root = Node(order) + keys = generate_random_keys(18, 1, 99) + print(keys) + print("=====") - # for key in keys: - # bptree_insert(root, key) + for key in keys: + bptree_insert(root, key) - # bptree_delete(root, 56) - # bptree_delete(root, 82) - # bptree_delete(root, 75) - # bptree_insert(root, 80) - # bptree_delete(root, 47) - # # bptree_delete(root, 80) - # bptree_delete(root, 21) - # bptree_delete(root, 22) - # bptree_delete(root, 12) - # bptree_delete(root, 8) - # bptree_print(root) + bptree_delete(root, 56) + bptree_delete(root, 12) + bptree_delete(root, 21) + bptree_delete(root, 47) + bptree_delete(root, 11) + bptree_delete(root, 86) + bptree_print(root) if __name__ == "__main__":