diff --git a/__main__.py b/__main__.py index c1d0f4f03014076c4f2008921a59772c73a559c1..303a7d9a4a695e5b756463ed7ac9a9b19346ca32 100644 --- a/__main__.py +++ b/__main__.py @@ -1,5 +1,7 @@ import random +from numpy import sort + class Node: def __init__(self, order): @@ -58,7 +60,7 @@ def insert(root, key): insert_non_full(leaf, key, None) -def redistribute_items(left_node, right_node, left_index, right_index): +def redistribute_keys(left_node, right_node, left_index, right_index): right_node.keys = left_node.keys[right_index:] left_node.keys = left_node.keys[:left_index] @@ -66,68 +68,64 @@ def redistribute_items(left_node, right_node, left_index, right_index): def split_leaf(node, key): virtual_insertion_index = array_binary_search(node.keys, key) median_index = len(node.keys) // 2 - right_node = Node(node.order) - right_node.is_leaf = node.is_leaf if virtual_insertion_index < median_index: median_value = node.keys[median_index - 1] - redistribute_items(node, right_node, median_index - 1, median_index - 1) + redistribute_keys(node, right_node, median_index - 1, median_index - 1) array_insert_sorted(node.keys, key) else: if virtual_insertion_index > median_index: median_value = node.keys[median_index] else: median_value = key - redistribute_items(node, right_node, median_index, median_index) + redistribute_keys(node, right_node, median_index, median_index) array_insert_sorted(right_node.keys, key) - # if key == node.keys[len(node.keys) // 2]: - # # I don't like it but without it the duplicates can't work. - # split_index = len(node.keys) // 2 + if not node.children: + # The node has no link to the next node, so a link is created. + node.children.append(right_node) + else: + # The node already has a link to the next node, the right node is linked to it and the node is linked to the right node. + right_node.children.append(node.children[0]) + node.children[0] = right_node return median_value, right_node +def redistribute_children(left_node, right_node, left_index, right_index): + right_node.children = left_node.children[right_index:] + left_node.children = left_node.children[:left_index] + + def split_internal(node, key, right_child_node): virtual_insertion_index = array_binary_search(node.keys, key) median_index = len(node.keys) // 2 - left_index = median_index - right_index = median_index + right_node = Node(node.order) + right_node.is_leaf = False if virtual_insertion_index < median_index: - abc = node.keys[median_index - 1] - left_index -= 1 - elif virtual_insertion_index > median_index: - abc = node.keys[median_index] - right_index += 1 - else: - abc = key - - split_right = Node(node.order) - split_right.is_leaf = node.is_leaf - split_right.keys = node.keys[right_index:] - node.keys = node.keys[:left_index] - - if key < abc: + # The key is virtually inserted to the left of the median index. + median_value = node.keys[median_index - 1] + redistribute_keys(node, right_node, median_index - 1, median_index) + redistribute_children(node, right_node, median_index, median_index) inserted_at_index = array_insert_sorted(node.keys, key) - elif key > abc: - inserted_at_index = array_insert_sorted(split_right.keys, key) - - if virtual_insertion_index < median_index: - split_right.children = node.children[median_index:] - node.children = node.children[:median_index] node.children.insert(inserted_at_index + 1, right_child_node) elif virtual_insertion_index > median_index: - split_right.children = node.children[median_index + 1 :] - node.children = node.children[: median_index + 1] - split_right.children.insert(inserted_at_index + 1, right_child_node) + # The key is virtually inserted to the right of the median index. + median_value = node.keys[median_index] + redistribute_keys(node, right_node, median_index, median_index + 1) + redistribute_children(node, right_node, median_index + 1, median_index + 1) + inserted_at_index = array_insert_sorted(right_node.keys, key) + right_node.children.insert(inserted_at_index + 1, right_child_node) else: - split_right.children = node.children[median_index + 1 :] - node.children = node.children[: median_index + 1] - split_right.children.insert(0, right_child_node) + # The key is virtually inserted at the median index. + median_value = key + redistribute_keys(node, right_node, median_index, median_index) + redistribute_children(node, right_node, median_index + 1, median_index + 1) + right_node.children.insert(0, right_child_node) - return abc, split_right + return median_value, right_node def tree_grow(root, median_value, split_right_node): @@ -168,10 +166,29 @@ def tree_print(root, depth=0): print(" " * depth, end="") print(root.keys) + if root.is_leaf: + return + for child in root.children: tree_print(child, depth + 1) +def extract_all_keys(root): + current = root + + while not current.is_leaf: + current = current.children[0] + + keys = [] + + while current.children: + keys += current.keys + current = current.children[0] + + keys += current.keys + return keys + + def generate_random_keys(length, min_key, max_key): keys = [] @@ -191,13 +208,15 @@ def main(): order = 2 root = Node(order) - keys = generate_random_keys(30, 1, 99) + keys = generate_random_keys(40, 1, 99) print(keys) for key in keys: insert(root, key) tree_print(root) + extracted_keys = extract_all_keys(root) + assert extracted_keys == sorted(keys) if __name__ == "__main__":