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

Deletion implementation

parent 2be51a64
No related branches found
No related tags found
No related merge requests found
...@@ -224,6 +224,10 @@ def bptree_find_smallest_key(root): ...@@ -224,6 +224,10 @@ def bptree_find_smallest_key(root):
return bptree_find_smallest_key(root.children[0]) return bptree_find_smallest_key(root.children[0])
def is_sibling_left_side(parent, node, sibling):
return find_child_index(parent, sibling) < find_child_index(parent, node)
def bptree_shrink(root): def bptree_shrink(root):
child = root.children[0] child = root.children[0]
root.keys = child.keys.copy() root.keys = child.keys.copy()
...@@ -231,26 +235,37 @@ def bptree_shrink(root): ...@@ -231,26 +235,37 @@ def bptree_shrink(root):
root.is_leaf = child.is_leaf root.is_leaf = child.is_leaf
def bptree_steal_internal(): def bptree_steal_internal(parent, node, child_index, sibling):
# TODO if is_sibling_left_side(parent, node, sibling):
pass node.keys.insert(0, parent.keys[child_index - 1])
parent.keys[child_index - 1] = sibling.keys[len(sibling.keys) - 1]
sibling.keys.pop(len(sibling.keys) - 1)
node.children.insert(0, sibling.children[len(sibling.children) - 1])
sibling.children.pop(len(sibling.children) - 1)
else:
node.keys.append(parent.keys[child_index])
parent.keys[child_index] = sibling.keys[0]
sibling.keys.pop(0)
node.children.append(sibling.children[0])
sibling.children.pop(0)
def bptree_steal_leaf(parent, node, child_index, sibling, sibling_side): def bptree_steal_leaf(parent, node, child_index, sibling):
if sibling_side == "l": if is_sibling_left_side(parent, node, sibling):
sibling_key = sibling.keys[len(sibling.keys) - 1] stealed_key = sibling.keys[len(sibling.keys) - 1]
sorted_array_delete(sibling.keys, sibling_key) sibling.keys.pop(len(sibling.keys) - 1)
sorted_array_insert(node.keys, sibling_key) parent.keys[child_index - 1] = stealed_key
parent.keys[child_index - 1] = sibling_key node.keys.insert(0, stealed_key)
elif sibling_side == "r": else:
sibling_key = sibling.keys[0] stealed_key = sibling.keys[0]
sorted_array_delete(sibling.keys, sibling_key) sibling.keys.pop(0)
sorted_array_insert(node.keys, sibling_key)
parent.keys[child_index] = sibling.keys[0] parent.keys[child_index] = sibling.keys[0]
node.keys.append(stealed_key)
def _bptree_merge(parent, main_node, secondary_node, pivot_index): def _bptree_merge(parent, main_node, secondary_node, pivot_index):
if not main_node.is_leaf: if not main_node.is_leaf:
print(pivot_index)
parent_key = parent.keys[pivot_index] parent_key = parent.keys[pivot_index]
main_node.keys.insert(0, parent_key) main_node.keys.insert(0, parent_key)
...@@ -265,11 +280,13 @@ def _bptree_merge(parent, main_node, secondary_node, pivot_index): ...@@ -265,11 +280,13 @@ def _bptree_merge(parent, main_node, secondary_node, pivot_index):
parent.children.pop(pivot_index) parent.children.pop(pivot_index)
def bptree_merge(parent, node, child_index, sibling, sibling_side): def bptree_merge(parent, node, sibling):
if sibling_side == "l": child_index = find_child_index(parent, node)
if is_sibling_left_side(parent, node, sibling):
# The sibling is merged into the node. # The sibling is merged into the node.
_bptree_merge(parent, node, sibling, child_index - 1) _bptree_merge(parent, node, sibling, child_index - 1)
elif sibling_side == "r": else:
# The node is merged into the sibling. # The node is merged into the sibling.
_bptree_merge(parent, sibling, node, child_index) _bptree_merge(parent, sibling, node, child_index)
...@@ -282,31 +299,24 @@ def find_child_index(parent, child): ...@@ -282,31 +299,24 @@ def find_child_index(parent, child):
return None return None
def bptree_find_sibling(parent, child_index): def bptree_find_sibling(parent, node):
child_index = find_child_index(parent, node)
if child_index == 0: if child_index == 0:
# Must take the sibling on the right. # Must take the sibling on the right.
sibling = parent.children[1] return parent.children[1]
sibling_position = "r" if child_index == len(parent.children) - 1:
elif child_index == len(parent.children) - 1:
# Must take the sibling on the left. # Must take the sibling on the left.
sibling = parent.children[len(parent.children) - 2] return parent.children[len(parent.children) - 2]
sibling_position = "l"
else:
# Can take the sibling from left or right. # Can take the sibling from left or right.
if len(parent.children[child_index - 1].keys) > parent.order: if len(parent.children[child_index - 1].keys) > parent.order:
# The left sibling has enough keys to borrow one. # The left sibling has enough keys to borrow one.
sibling = parent.children[child_index - 1] return parent.children[child_index - 1]
sibling_position = "l" if len(parent.children[child_index + 1].keys) > parent.order:
elif len(parent.children[child_index + 1].keys) > parent.order: # The right sibling has enough keys to borrow one.
# The right sibling has enough keys to borrow one. return parent.children[child_index + 1]
sibling = parent.children[child_index + 1] # A merge between the node and the left sibling is required.
sibling_position = "r" return parent.children[child_index - 1]
else:
# A merge between the node and the left sibling is required.
sibling = parent.children[child_index - 1]
sibling_position = "l"
return sibling, sibling_position
def _bptree_delete(root, parents, node, key): def _bptree_delete(root, parents, node, key):
...@@ -316,40 +326,27 @@ def _bptree_delete(root, parents, node, key): ...@@ -316,40 +326,27 @@ def _bptree_delete(root, parents, node, key):
parent = parents.pop() parent = parents.pop()
if node.is_leaf: if node.is_leaf:
keys_length = len(node.keys)
sorted_array_delete(node.keys, key) sorted_array_delete(node.keys, key)
if keys_length == node.order and node != root: if node != root and len(node.keys) < node.order:
child_index = find_child_index(parent, node) child_index = find_child_index(parent, node)
sibling, sibling_side = bptree_find_sibling(parent, child_index) sibling = bptree_find_sibling(parent, node)
if len(sibling.keys) == sibling.order:
# There is not enough key in the left and right siblings.
bptree_merge(parent, node, child_index, sibling, sibling_side)
if parent == root and len(parent.keys) == 0:
bptree_shrink(root)
parent = None
else:
# There are enough keys in the sibling to steal one.
bptree_steal_leaf(parent, node, child_index, sibling, sibling_side)
else:
if node != root and len(node.keys) < node.order:
child_index = find_child_index(parent, node)
sibling, sibling_side = bptree_find_sibling(parent, child_index)
if len(sibling.keys) == sibling.order: if len(sibling.keys) == sibling.order:
bptree_merge(parent, node, child_index, sibling, sibling_side) bptree_merge(parent, node, sibling)
if parent == root and len(parent.keys) == 0: if parent == root and len(parent.keys) == 0:
bptree_shrink(root) bptree_shrink(root)
parent = None parent = None
else:
if node.is_leaf:
bptree_steal_leaf(parent, node, child_index, sibling)
else: else:
print("???????????") bptree_steal_internal(parent, node, child_index, sibling)
if len(node.children) > 0 and is_value_in_array(node.keys, key): if not node.is_leaf and len(node.children) > 0 and is_value_in_array(node.keys, key):
index = find_value_index_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]) node.keys[index] = bptree_find_smallest_key(node.children[index + 1])
if parent is not None: if parent is not None:
_bptree_delete(root, parents, parent, key) _bptree_delete(root, parents, parent, key)
...@@ -442,16 +439,17 @@ def generate_random_keys(length, min_key, max_key): ...@@ -442,16 +439,17 @@ def generate_random_keys(length, min_key, max_key):
def main(): def main():
a = 2 a = 2
random.seed(a) random.seed(a)
order = 2 order = 2
root = Node(order) # =====================================================================
keys = generate_random_keys(40, 1, 99)
print(keys)
for key in keys: # root = Node(order)
bptree_insert(root, key) # keys = generate_random_keys(40, 1, 99)
# print(keys)
bptree_print(root) # for key in keys:
# bptree_insert(root, key)
# bptree_print(root)
# extracted_keys = bptree_extract_all_keys(root) # extracted_keys = bptree_extract_all_keys(root)
# assert extracted_keys == sorted(keys) # assert extracted_keys == sorted(keys)
...@@ -467,20 +465,27 @@ def main(): ...@@ -467,20 +465,27 @@ def main():
# assert not bptree_search(root, random_key) # assert not bptree_search(root, random_key)
# root = Node(order) # =====================================================================
# keys = generate_random_keys(30, 1, 99)
# print(keys)
# print("=====")
# for key in keys: root = Node(order)
# bptree_insert(root, key) keys = generate_random_keys(30, 1, 99)
print(keys)
print("=====")
# bptree_delete(root, 65) for key in keys:
# bptree_delete(root, 57) bptree_insert(root, key)
# bptree_delete(root, 47)
# # bptree_delete(root, 65)
# bptree_print(root) bptree_delete(root, 65)
bptree_delete(root, 57)
bptree_delete(root, 47)
bptree_delete(root, 28)
bptree_delete(root, 51)
bptree_insert(root, 100)
bptree_delete(root, 48)
bptree_delete(root, 41)
bptree_delete(root, 60)
bptree_print(root)
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -87,6 +87,14 @@ bool IntegerArray_binary_search(IntegerArray *array, uint64_t item, int *index) ...@@ -87,6 +87,14 @@ bool IntegerArray_binary_search(IntegerArray *array, uint64_t item, int *index)
return *index != -1; return *index != -1;
} }
void IntegerArray_delete_at_index(IntegerArray *array, int index) {
for (int i = index; i < array->size; i++) {
array->items[i] = array->items[i + 1];
}
array->size--;
}
void IntegerArray_print(IntegerArray *array) { void IntegerArray_print(IntegerArray *array) {
printf("["); printf("[");
......
...@@ -21,6 +21,7 @@ void IntegerArray_insert_at_index(IntegerArray *array, int index, uint64_t item) ...@@ -21,6 +21,7 @@ void IntegerArray_insert_at_index(IntegerArray *array, int index, uint64_t item)
void IntegerArray_append(IntegerArray *array, uint64_t item); void IntegerArray_append(IntegerArray *array, uint64_t item);
bool IntegerArray_binary_search(IntegerArray *array, uint64_t item, int *index); bool IntegerArray_binary_search(IntegerArray *array, uint64_t item, int *index);
void IntegerArray_delete_sorted(IntegerArray *array, uint64_t item); void IntegerArray_delete_sorted(IntegerArray *array, uint64_t item);
void IntegerArray_delete_at_index(IntegerArray *array, int index);
void IntegerArray_print(IntegerArray *array); void IntegerArray_print(IntegerArray *array);
void IntegerArray_clear(IntegerArray *array); void IntegerArray_clear(IntegerArray *array);
void IntegerArray_copy(IntegerArray *src, IntegerArray *dest); void IntegerArray_copy(IntegerArray *src, IntegerArray *dest);
......
...@@ -259,3 +259,138 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) { ...@@ -259,3 +259,138 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) {
} }
// Deletion // Deletion
static uint64_t find_smallest_key(BPTreeNode *root);
static int find_child_index(BPTreeNode *parent, BPTreeNode *child);
static bool is_sibling_left_side(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling);
static void shrink(BPTreeNode *root);
static void steal_internal(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling);
static void steal_leaf(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling);
static void _bptree_merge(BPTreeNode *parent, BPTreeNode *main_node, BPTreeNode *secondary_node, int pivot_index);
static void bptree_merge(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling);
static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node);
static uint64_t find_smallest_key(BPTreeNode *root) {
if (root->is_leaf) {
return root->keys->items[0];
}
return find_smallest_key(root->children->items[0]);
}
static int find_child_index(BPTreeNode *parent, BPTreeNode *child) {
for (int i = 0; i < parent->children->size; i++) {
if (child == parent->children->items[i]) {
return i;
}
}
return -1;
}
static bool is_sibling_left_side(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) {
return find_child_index(parent, sibling) < find_child_index(parent, node);
}
static void shrink(BPTreeNode *root) {
BPTreeNode *child = root->children->items[0];
root->is_leaf = child->is_leaf;
// No keys, it's obvious
// IntegerArray_clear(root->keys);
IntegerArray_copy(child->keys, root->keys);
BPTreeNodeArray_clear(root->children);
BPTreeNodeArray_copy(child->children, root->children);
BPTreeNodeArray_clear(child->children);
BPTree_destroy(&child);
}
static void steal_internal(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling) {
if (is_sibling_left_side(parent, node, sibling)) {
IntegerArray_insert_at_index(node->keys, 0, parent->keys->items[child_index - 1]);
parent->keys->items[child_index - 1] = sibling->keys->items[sibling->keys->size - 1];
IntegerArray_delete_at_index(sibling->keys, sibling->keys->size - 1);
BPTreeNodeArray_insert_at_index(node->children, 0, sibling->children->items[sibling->children->size - 1]);
BPTreeNodeArray_delete_at_index(sibling->children, sibling->children->size - 1);
} else {
IntegerArray_append(node->keys, parent->keys->items[child_index]);
parent->keys->items[child_index] = sibling->keys->items[0];
IntegerArray_delete_at_index(sibling->keys, 0);
BPTreeNodeArray_append(node->children, sibling->children->items[0]);
BPTreeNodeArray_delete_at_index(sibling->children, 0);
}
}
static void steal_leaf(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling) {
if (is_sibling_left_side(parent, node, sibling)) {
uint64_t stealed_key = sibling->keys->items[sibling->keys->size - 1];
IntegerArray_delete_at_index(sibling->keys, sibling->keys->size - 1);
parent->keys->items[child_index - 1] = stealed_key;
IntegerArray_insert_at_index(node->keys, 0, stealed_key);
} else {
uint64_t stealed_key = sibling->keys->items[0];
IntegerArray_delete_at_index(sibling->keys, 0);
parent->keys->items[child_index] = sibling->keys->items[0];
IntegerArray_append(node->keys, stealed_key);
}
}
static void _bptree_merge(BPTreeNode *parent, BPTreeNode *main_node, BPTreeNode *secondary_node, int pivot_index) {
if (!main_node->is_leaf) {
IntegerArray_insert_at_index(main_node->keys, 0, parent->keys->items[pivot_index]);
}
for (int i = secondary_node->keys->size - 1; i >= 0; i--) {
IntegerArray_insert_at_index(main_node->keys, 0, secondary_node->keys->items[i]);
}
if (!main_node->is_leaf) {
for (int i = secondary_node->children->size - 1; i >= 0; i--) {
BPTreeNodeArray_insert_at_index(main_node->children, 0, secondary_node->children->items[i]);
}
}
IntegerArray_delete_at_index(parent->keys, pivot_index);
BPTreeNodeArray_delete_at_index(parent->children, pivot_index);
}
static void bptree_merge(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) {
int child_index = find_child_index(parent, node);
if (is_sibling_left_side(parent, node, sibling)) {
_bptree_merge(parent, node, sibling, child_index - 1);
} else {
_bptree_merge(parent, sibling, node, child_index);
}
}
static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node) {
int child_index = find_child_index(parent, node);
if (child_index == 0) {
return parent->children->items[1];
}
if (child_index == parent->children->size - 1) {
return parent->children->items[parent->children->size - 2];
}
if (parent->children->items[child_index - 1]->keys->size > parent->order) {
return parent->children->items[child_index - 1];
}
if (parent->children->items[child_index + 1]->keys->size > parent->order) {
return parent->children->items[child_index + 1];
}
return parent->children->items[child_index - 1];
}
static void _bptree_delete(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNode *node, uint64_t key) {
BPTreeNode *parent = NULL;
}
void BPTree_delete(BPTreeNode *root, uint64_t key) {
}
...@@ -27,4 +27,6 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data); ...@@ -27,4 +27,6 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data);
// Deletion // Deletion
void BPTree_delete(BPTreeNode *root, uint64_t key);
#endif #endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment