Skip to content
Snippets Groups Projects
Commit 07f18a24 authored by florian.burgener's avatar florian.burgener
Browse files

Deletion

parent c9ce881c
Branches
No related tags found
No related merge requests found
...@@ -69,18 +69,6 @@ class Node: ...@@ -69,18 +69,6 @@ class Node:
self.children = [] self.children = []
def find_leaf(root, key):
parents = []
current = root
while not current.is_leaf:
parents.append(current)
children_index = lower_bound(current.keys, key)
current = current.children[children_index]
return parents, current
def node_is_full(node): def node_is_full(node):
return len(node.keys) == 2 * node.order return len(node.keys) == 2 * node.order
...@@ -191,8 +179,20 @@ def insert_non_full(node, key, previous_split_right_node): ...@@ -191,8 +179,20 @@ 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 insertion_find_leaf(root, key):
parents = []
current = root
while not current.is_leaf:
parents.append(current)
children_index = lower_bound(current.keys, key)
current = current.children[children_index]
return parents, current
def bptree_insert(root, key): def bptree_insert(root, key):
parents, leaf = find_leaf(root, key) parents, leaf = insertion_find_leaf(root, key)
if node_is_full(leaf): if node_is_full(leaf):
insert_full(root, parents, leaf, key, None) insert_full(root, parents, leaf, key, None)
...@@ -205,15 +205,80 @@ def bptree_insert(root, key): ...@@ -205,15 +205,80 @@ def bptree_insert(root, key):
# DELETION : START # DELETION : START
def bptree_delete(root, key): def deletion_find_leaf(root, key):
parents, leaf = find_leaf(root, key) parents = []
current = root
while not current.is_leaf:
parents.append(current)
children_index = lower_bound(current.keys, key)
if children_index < len(current.keys) and current.keys[children_index] == key:
children_index += 1
current = current.children[children_index]
return parents, current
if not is_value_in_array(leaf.keys, key):
return
def bptree_find_smallest_key(root):
if root.is_leaf:
return root.keys[0]
return bptree_find_smallest_key(root.children[0])
def bptree_shrink(root):
right_child = root.children[1]
root.keys = right_child.keys
root.children = right_child.children
def bptree_delete_internal(root, parents, node, key):
if node != root:
parent = parents.pop()
if len(node.keys) < node.order and node != root:
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):
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)
def bptree_delete_leaf(root, parents, leaf, key):
if len(leaf.keys) > leaf.order: if len(leaf.keys) > leaf.order:
deletion_index = find_value_index_in_array(leaf.keys, key) deletion_index = find_value_index_in_array(leaf.keys, key)
leaf.keys.pop(deletion_index) leaf.keys.pop(deletion_index)
bptree_delete_internal(root, parents, parents.pop(), key)
else: else:
deletion_index = find_value_index_in_array(leaf.keys, key) deletion_index = find_value_index_in_array(leaf.keys, key)
leaf.keys.pop(deletion_index) leaf.keys.pop(deletion_index)
...@@ -226,24 +291,72 @@ def bptree_delete(root, key): ...@@ -226,24 +291,72 @@ def bptree_delete(root, key):
children_index = i children_index = i
if children_index == 0: if children_index == 0:
sibling = parent.children[children_index + 1] # Must take the sibling on the right.
else: 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 = parent.children[children_index - 1]
sibling_position = "l"
if len(sibling.keys) == leaf.order:
pass
else: else:
# Works only if children_index = 0 # Can take the sibling from left or right.
borrowed_key = sibling.keys[0] if len(parent.children[children_index - 1].keys) > leaf.order:
sibling.keys.pop(0) # The left sibling has enough keys to borrow one.
leaf.keys.append(borrowed_key) sibling = parent.children[children_index - 1]
parent.keys[0] = sibling.keys[0] 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]
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)
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)
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)
array_insert_sorted(leaf.keys, sibling_key)
parent.keys[children_index] = sibling.keys[0]
bptree_delete_internal(root, parents, parent, key)
def bptree_delete(root, key):
parents, leaf = deletion_find_leaf(root, key)
if not is_value_in_array(leaf.keys, key):
return
bptree_delete_leaf(root, parents, leaf, key)
# DELETION : END # DELETION : END
def bptree_search(root, key): def bptree_search(root, key):
# BUG !!!
if root.is_leaf: if root.is_leaf:
return is_value_in_array(root.keys, key) return is_value_in_array(root.keys, key)
...@@ -300,7 +413,8 @@ def generate_random_keys(length, min_key, max_key): ...@@ -300,7 +413,8 @@ def generate_random_keys(length, min_key, max_key):
def main(): def main():
random.seed(0) a = 2
random.seed(a)
order = 2 order = 2
# root = Node(order) # root = Node(order)
...@@ -327,16 +441,23 @@ def main(): ...@@ -327,16 +441,23 @@ def main():
# assert not bptree_search(root, random_key) # assert not bptree_search(root, random_key)
root = Node(order) root = Node(order)
keys = generate_random_keys(8, 1, 99) keys = generate_random_keys(18, 1, 99)
print(keys) print(keys)
print("=====") print("=====")
for key in keys: for key in keys:
bptree_insert(root, key) bptree_insert(root, key)
bptree_delete(root, 51) bptree_delete(root, 56)
# bptree_delete(root, 52) bptree_delete(root, 82)
bptree_delete(root, 34) 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_print(root)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment