Skip to content
Snippets Groups Projects
Commit c9ce881c authored by Florian Burgener's avatar Florian Burgener
Browse files

Refactoring

parent 4675e8d3
No related branches found
No related tags found
No related merge requests found
import random import random
from numpy import sort
class Node:
def __init__(self, order):
self.order = order
self.is_leaf = True
self.keys = []
self.children = []
def lower_bound(array, value): def lower_bound(array, value):
low = 0 low = 0
...@@ -45,12 +35,40 @@ def is_value_in_array(array, value): ...@@ -45,12 +35,40 @@ def is_value_in_array(array, value):
return False return False
def find_value_index_in_array(array, value):
low = 0
high = len(array) - 1
while low <= high:
m = (low + high) // 2
if array[m] < value:
low = m + 1
elif array[m] > value:
high = m - 1
else:
return m
return None
def array_insert_sorted(array, value): def array_insert_sorted(array, value):
index = lower_bound(array, value) index = lower_bound(array, value)
array.insert(index, value) array.insert(index, value)
return index return index
# B+ Tree : START
class Node:
def __init__(self, order):
self.order = order
self.is_leaf = True
self.keys = []
self.children = []
def find_leaf(root, key): def find_leaf(root, key):
parents = [] parents = []
current = root current = root
...@@ -67,13 +85,7 @@ def node_is_full(node): ...@@ -67,13 +85,7 @@ def node_is_full(node):
return len(node.keys) == 2 * node.order return len(node.keys) == 2 * node.order
def insert(root, key): # INSERTION : START
parents, leaf = find_leaf(root, key)
if node_is_full(leaf):
insert_full(root, parents, leaf, key, None)
else:
insert_non_full(leaf, key, None)
def redistribute_keys(left_node, right_node, left_index, right_index): def redistribute_keys(left_node, right_node, left_index, right_index):
...@@ -145,7 +157,7 @@ def split_internal(node, key, right_child_node): ...@@ -145,7 +157,7 @@ def split_internal(node, key, right_child_node):
return median_value, right_node return median_value, right_node
def tree_grow(root, median_value, split_right_node): def bptree_grow(root, median_value, split_right_node):
left_node = Node(root.order) left_node = Node(root.order)
left_node.is_leaf = split_right_node.is_leaf left_node.is_leaf = split_right_node.is_leaf
left_node.keys = root.keys left_node.keys = root.keys
...@@ -162,7 +174,7 @@ def insert_full(root, parents, node, key, previous_split_right_node): ...@@ -162,7 +174,7 @@ def insert_full(root, parents, node, key, previous_split_right_node):
median_value, split_right_node = split_internal(node, key, previous_split_right_node) median_value, split_right_node = split_internal(node, key, previous_split_right_node)
if node == root: if node == root:
tree_grow(root, median_value, split_right_node) bptree_grow(root, median_value, split_right_node)
else: else:
parent = parents.pop() parent = parents.pop()
...@@ -179,7 +191,59 @@ def insert_non_full(node, key, previous_split_right_node): ...@@ -179,7 +191,59 @@ def insert_non_full(node, key, previous_split_right_node):
node.children.insert(inserted_at_index + 1, previous_split_right_node) node.children.insert(inserted_at_index + 1, previous_split_right_node)
def tree_search(root, key): def bptree_insert(root, key):
parents, leaf = find_leaf(root, key)
if node_is_full(leaf):
insert_full(root, parents, leaf, key, None)
else:
insert_non_full(leaf, key, None)
# INSERTION : END
# DELETION : START
def bptree_delete(root, key):
parents, leaf = find_leaf(root, key)
if not is_value_in_array(leaf.keys, key):
return
if len(leaf.keys) > leaf.order:
deletion_index = find_value_index_in_array(leaf.keys, key)
leaf.keys.pop(deletion_index)
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:
sibling = parent.children[children_index + 1]
else:
sibling = parent.children[children_index - 1]
if len(sibling.keys) == leaf.order:
pass
else:
# Works only if children_index = 0
borrowed_key = sibling.keys[0]
sibling.keys.pop(0)
leaf.keys.append(borrowed_key)
parent.keys[0] = sibling.keys[0]
# DELETION : END
def bptree_search(root, key):
if root.is_leaf: if root.is_leaf:
return is_value_in_array(root.keys, key) return is_value_in_array(root.keys, key)
...@@ -188,10 +252,10 @@ def tree_search(root, key): ...@@ -188,10 +252,10 @@ def tree_search(root, key):
if children_index < len(root.keys) and root.keys[children_index] == key: if children_index < len(root.keys) and root.keys[children_index] == key:
children_index += 1 children_index += 1
return tree_search(root.children[children_index], key) return bptree_search(root.children[children_index], key)
def tree_print(root, depth=0): def bptree_print(root, depth=0):
print(" " * depth, end="") print(" " * depth, end="")
print(root.keys) print(root.keys)
...@@ -199,10 +263,10 @@ def tree_print(root, depth=0): ...@@ -199,10 +263,10 @@ def tree_print(root, depth=0):
return return
for child in root.children: for child in root.children:
tree_print(child, depth + 1) bptree_print(child, depth + 1)
def extract_all_keys(root): def bptree_extract_all_keys(root):
current = root current = root
while not current.is_leaf: while not current.is_leaf:
...@@ -218,6 +282,9 @@ def extract_all_keys(root): ...@@ -218,6 +282,9 @@ def extract_all_keys(root):
return keys return keys
# B+ Tree : END
def generate_random_keys(length, min_key, max_key): def generate_random_keys(length, min_key, max_key):
keys = [] keys = []
...@@ -236,28 +303,41 @@ def main(): ...@@ -236,28 +303,41 @@ def main():
random.seed(0) random.seed(0)
order = 2 order = 2
root = Node(order) # root = Node(order)
keys = generate_random_keys(40, 1, 99) # keys = generate_random_keys(40, 1, 99)
print(keys) # print(keys)
for key in keys: # for key in keys:
insert(root, key) # bptree_insert(root, key)
tree_print(root) # bptree_print(root)
extracted_keys = extract_all_keys(root) # extracted_keys = bptree_extract_all_keys(root)
assert extracted_keys == sorted(keys) # assert extracted_keys == sorted(keys)
for key in keys: # for key in keys:
assert tree_search(root, key) # assert bptree_search(root, key)
for _ in range(5): # for _ in range(5):
while True: # while True:
random_key = random.randint(1, 99) # random_key = random.randint(1, 99)
if random_key not in keys: # if random_key not in keys:
break # break
# assert not bptree_search(root, random_key)
root = Node(order)
keys = generate_random_keys(8, 1, 99)
print(keys)
print("=====")
for key in keys:
bptree_insert(root, key)
assert not tree_search(root, random_key) bptree_delete(root, 51)
# bptree_delete(root, 52)
bptree_delete(root, 34)
bptree_print(root)
if __name__ == "__main__": if __name__ == "__main__":
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment