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

More refactoring

parent 11a5e65f
No related branches found
No related tags found
No related merge requests found
...@@ -149,6 +149,16 @@ void BPTreeNodeArray_append(BPTreeNodeArray *array, BPTreeNode *item) { ...@@ -149,6 +149,16 @@ void BPTreeNodeArray_append(BPTreeNodeArray *array, BPTreeNode *item) {
array->size++; array->size++;
} }
int BPTreeNodeArray_search(BPTreeNodeArray *array, BPTreeNode *item) {
for (int i = 0; i < array->size; i++) {
if (array->items[i] == item) {
return i;
}
}
return -1;
}
void BPTreeNodeArray_delete_at_index(BPTreeNodeArray *array, int index) { void BPTreeNodeArray_delete_at_index(BPTreeNodeArray *array, int index) {
for (int i = index; i < array->size - 1; i++) { for (int i = index; i < array->size - 1; i++) {
array->items[i] = array->items[i + 1]; array->items[i] = array->items[i + 1];
......
...@@ -39,6 +39,7 @@ void BPTreeNodeArray_destroy(BPTreeNodeArray **array); ...@@ -39,6 +39,7 @@ void BPTreeNodeArray_destroy(BPTreeNodeArray **array);
void BPTreeNodeArray_insert_at_index(BPTreeNodeArray *array, int index, BPTreeNode *item); void BPTreeNodeArray_insert_at_index(BPTreeNodeArray *array, int index, BPTreeNode *item);
void BPTreeNodeArray_append(BPTreeNodeArray *array, BPTreeNode *item); void BPTreeNodeArray_append(BPTreeNodeArray *array, BPTreeNode *item);
int BPTreeNodeArray_search(BPTreeNodeArray *array, BPTreeNode *item);
void BPTreeNodeArray_delete_at_index(BPTreeNodeArray *array, int index); void BPTreeNodeArray_delete_at_index(BPTreeNodeArray *array, int index);
BPTreeNode *BPTreeNodeArray_pop(BPTreeNodeArray *array); BPTreeNode *BPTreeNodeArray_pop(BPTreeNodeArray *array);
void BPTreeNodeArray_clear(BPTreeNodeArray *array); void BPTreeNodeArray_clear(BPTreeNodeArray *array);
......
...@@ -33,7 +33,7 @@ static BPTreeNode *find_leaf(BPTreeNode *root, uint64_t key, BPTreeNodeArray **p ...@@ -33,7 +33,7 @@ static BPTreeNode *find_leaf(BPTreeNode *root, uint64_t key, BPTreeNodeArray **p
return current; return current;
} }
// ======= // BPTreeNode
static void BPTreeNode_destroy(BPTreeNode **node) { static void BPTreeNode_destroy(BPTreeNode **node) {
IntegerArray_destroy(&(*node)->keys); IntegerArray_destroy(&(*node)->keys);
...@@ -43,7 +43,7 @@ static void BPTreeNode_destroy(BPTreeNode **node) { ...@@ -43,7 +43,7 @@ static void BPTreeNode_destroy(BPTreeNode **node) {
*node = NULL; *node = NULL;
} }
// ======= // BPTree
BPTreeNode *BPTree_init(int order) { BPTreeNode *BPTree_init(int order) {
BPTreeNode *root = (BPTreeNode *)malloc(sizeof(BPTreeNode)); BPTreeNode *root = (BPTreeNode *)malloc(sizeof(BPTreeNode));
...@@ -102,7 +102,7 @@ bool BPTree_search(BPTreeNode *root, uint64_t key, uint64_t *data) { ...@@ -102,7 +102,7 @@ bool BPTree_search(BPTreeNode *root, uint64_t key, uint64_t *data) {
return BPTree_search(root->children->items[child_index], key, data); return BPTree_search(root->children->items[child_index], key, data);
} }
// Insertion // BPTree : Insertion
static void redistribute_keys(BPTreeNode *left_node, BPTreeNode *right_node, int left_index, int right_index); static void redistribute_keys(BPTreeNode *left_node, BPTreeNode *right_node, int left_index, int right_index);
static void redistribute_children(BPTreeNode *left_node, BPTreeNode *right_node, int left_index, int right_index); static void redistribute_children(BPTreeNode *left_node, BPTreeNode *right_node, int left_index, int right_index);
...@@ -269,41 +269,68 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) { ...@@ -269,41 +269,68 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) {
BPTreeNodeArray_destroy(&parents); BPTreeNodeArray_destroy(&parents);
} }
// Deletion // BPTree : Deletion
static bool _BPTree_delete(BPTreeNode *node, uint64_t key, BPTreeNode *parent);
static BPTreeNode *traverse(BPTreeNode *node, uint64_t key);
static uint64_t find_smallest_key(BPTreeNode *root); 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 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 _merge(BPTreeNode *parent, BPTreeNode *main_node, BPTreeNode *secondary_node, int pivot_index);
static void merge(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling);
static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node);
static bool _BPTree_delete(BPTreeNode *root, uint64_t key, BPTreeNode *parent);
static BPTreeNode *traverse(BPTreeNode *root, uint64_t key);
static void deletion_rebalance(BPTreeNode *root, BPTreeNode *parent); static void deletion_rebalance(BPTreeNode *root, BPTreeNode *parent);
static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node);
static void merge(BPTreeNode *parent, BPTreeNode *left_node, BPTreeNode *right_node);
static void steal_leaf(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling);
static void steal_internal(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling);
static bool is_sibling_left_side(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling);
bool BPTree_delete(BPTreeNode *root, uint64_t key) {
return _BPTree_delete(root, key, NULL);
}
static bool _BPTree_delete(BPTreeNode *root, uint64_t key, BPTreeNode *parent) {
if (!root->is_leaf && !_BPTree_delete(traverse(root, key), key, root)) {
return false;
}
int index;
bool is_found = IntegerArray_binary_search(root->keys, key, &index);
if (root->is_leaf && !is_found) {
return false;
}
static uint64_t find_smallest_key(BPTreeNode *root) {
if (root->is_leaf) { if (root->is_leaf) {
return root->keys->items[0]; IntegerArray_delete_at_index(root->keys, index);
IntegerArray_delete_at_index(root->data, index);
} else if (is_found) {
root->keys->items[index] = find_smallest_key(root->children->items[index + 1]);
} }
return find_smallest_key(root->children->items[0]); if (parent == NULL && root->keys->size == 0) {
shrink(root);
}
if (parent != NULL && root->keys->size < root->order) {
deletion_rebalance(root, parent);
}
return true;
} }
static int find_child_index(BPTreeNode *parent, BPTreeNode *child) { static BPTreeNode *traverse(BPTreeNode *node, uint64_t key) {
for (int i = 0; i < parent->children->size; i++) { int virtual_insertion_index = lower_bound(node->keys, key);
if (child == parent->children->items[i]) {
return i; if (virtual_insertion_index < node->keys->size && node->keys->items[virtual_insertion_index] == key) {
virtual_insertion_index += 1;
} }
return node->children->items[virtual_insertion_index];
} }
return -1; static uint64_t find_smallest_key(BPTreeNode *root) {
if (root->is_leaf) {
return root->keys->items[0];
} }
static bool is_sibling_left_side(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) { return find_smallest_key(root->children->items[0]);
return find_child_index(parent, sibling) < find_child_index(parent, node);
} }
static void shrink(BPTreeNode *root) { static void shrink(BPTreeNode *root) {
...@@ -319,154 +346,114 @@ static void shrink(BPTreeNode *root) { ...@@ -319,154 +346,114 @@ static void shrink(BPTreeNode *root) {
BPTreeNode_destroy(&child); BPTreeNode_destroy(&child);
} }
static void steal_internal(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling) { static void deletion_rebalance(BPTreeNode *node, BPTreeNode *parent) {
BPTreeNode *sibling = find_sibling(parent, node);
if (sibling->keys->size == sibling->order) {
if (is_sibling_left_side(parent, node, sibling)) { if (is_sibling_left_side(parent, node, sibling)) {
IntegerArray_insert_at_index(node->keys, 0, parent->keys->items[child_index - 1]); merge(parent, sibling, node);
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 { } else {
IntegerArray_append(node->keys, parent->keys->items[child_index]); merge(parent, node, sibling);
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);
}
} }
} else if (node->is_leaf) {
static void steal_leaf(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling) { steal_leaf(parent, node, sibling);
if (is_sibling_left_side(parent, node, sibling)) {
uint64_t stealed_key = sibling->keys->items[sibling->keys->size - 1];
IntegerArray_insert_at_index(node->keys, 0, stealed_key);
IntegerArray_delete_at_index(sibling->keys, sibling->keys->size - 1);
parent->keys->items[child_index - 1] = stealed_key;
// The data must also be stolen.
IntegerArray_insert_at_index(node->data, 0, sibling->data->items[sibling->data->size - 1]);
IntegerArray_delete_at_index(sibling->data, sibling->data->size - 1);
} else { } else {
uint64_t stealed_key = sibling->keys->items[0]; steal_internal(parent, node, sibling);
IntegerArray_append(node->keys, stealed_key);
IntegerArray_delete_at_index(sibling->keys, 0);
parent->keys->items[child_index] = sibling->keys->items[0];
// The data must also be stolen.
IntegerArray_append(node->data, sibling->data->items[0]);
IntegerArray_delete_at_index(sibling->data, 0);
} }
} }
static void _merge(BPTreeNode *parent, BPTreeNode *main_node, BPTreeNode *secondary_node, int pivot_index) { static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node) {
if (!main_node->is_leaf) { int index_in_children = BPTreeNodeArray_search(parent->children, node);
IntegerArray_insert_at_index(main_node->keys, 0, parent->keys->items[pivot_index]);
}
// Merge the keys. if (index_in_children == 0) {
for (int i = secondary_node->keys->size - 1; i >= 0; i--) { return parent->children->items[1];
IntegerArray_insert_at_index(main_node->keys, 0, secondary_node->keys->items[i]);
} }
// Merge the data. if (index_in_children == parent->children->size - 1) {
for (int i = secondary_node->data->size - 1; i >= 0; i--) { return parent->children->items[parent->children->size - 2];
IntegerArray_insert_at_index(main_node->data, 0, secondary_node->data->items[i]);
} }
// Merge the children. if (parent->children->items[index_in_children - 1]->keys->size > parent->order) {
for (int i = secondary_node->children->size - 1; i >= 0; i--) { return parent->children->items[index_in_children - 1];
BPTreeNodeArray_insert_at_index(main_node->children, 0, secondary_node->children->items[i]);
} }
IntegerArray_delete_at_index(parent->keys, pivot_index); if (parent->children->items[index_in_children + 1]->keys->size > parent->order) {
BPTreeNodeArray_delete_at_index(parent->children, pivot_index); return parent->children->items[index_in_children + 1];
BPTreeNode_destroy(&secondary_node);
} }
static void merge(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) { return parent->children->items[index_in_children - 1];
int child_index = find_child_index(parent, node);
if (is_sibling_left_side(parent, node, sibling)) {
_merge(parent, node, sibling, child_index - 1);
} else {
_merge(parent, sibling, node, child_index);
}
} }
static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node) { static void merge(BPTreeNode *parent, BPTreeNode *left_node, BPTreeNode *right_node) {
int child_index = find_child_index(parent, node); int index_in_children = BPTreeNodeArray_search(parent->children, left_node);
if (child_index == 0) { if (!right_node->is_leaf) {
return parent->children->items[1]; IntegerArray_insert_at_index(right_node->keys, 0, parent->keys->items[index_in_children]);
} }
if (child_index == parent->children->size - 1) { // Merge the keys.
return parent->children->items[parent->children->size - 2]; for (int i = left_node->keys->size - 1; i >= 0; i--) {
} IntegerArray_insert_at_index(right_node->keys, 0, left_node->keys->items[i]);
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) { // Merge the data.
return parent->children->items[child_index + 1]; for (int i = left_node->data->size - 1; i >= 0; i--) {
IntegerArray_insert_at_index(right_node->data, 0, left_node->data->items[i]);
} }
return parent->children->items[child_index - 1]; // Merge the children.
for (int i = left_node->children->size - 1; i >= 0; i--) {
BPTreeNodeArray_insert_at_index(right_node->children, 0, left_node->children->items[i]);
} }
static BPTreeNode *traverse(BPTreeNode *root, uint64_t key) { IntegerArray_delete_at_index(parent->keys, index_in_children);
int virtual_insertion_index = lower_bound(root->keys, key); BPTreeNodeArray_delete_at_index(parent->children, index_in_children);
if (virtual_insertion_index < root->keys->size && root->keys->items[virtual_insertion_index] == key) { BPTreeNode_destroy(&left_node);
virtual_insertion_index += 1;
} }
return root->children->items[virtual_insertion_index]; static void steal_leaf(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) {
} int index_in_children = BPTreeNodeArray_search(parent->children, node);
static void deletion_rebalance(BPTreeNode *root, BPTreeNode *parent) { if (is_sibling_left_side(parent, node, sibling)) {
int child_index = find_child_index(parent, root); uint64_t stealed_key = sibling->keys->items[sibling->keys->size - 1];
BPTreeNode *sibling = find_sibling(parent, root); IntegerArray_insert_at_index(node->keys, 0, stealed_key);
IntegerArray_delete_at_index(sibling->keys, sibling->keys->size - 1);
parent->keys->items[index_in_children - 1] = stealed_key;
if (sibling->keys->size == sibling->order) { // The data must also be stolen.
merge(parent, root, sibling); IntegerArray_insert_at_index(node->data, 0, sibling->data->items[sibling->data->size - 1]);
} else if (root->is_leaf) { IntegerArray_delete_at_index(sibling->data, sibling->data->size - 1);
steal_leaf(parent, root, child_index, sibling);
} else { } else {
steal_internal(parent, root, child_index, sibling); uint64_t stealed_key = sibling->keys->items[0];
} IntegerArray_append(node->keys, stealed_key);
} IntegerArray_delete_at_index(sibling->keys, 0);
parent->keys->items[index_in_children] = sibling->keys->items[0];
static bool _BPTree_delete(BPTreeNode *root, uint64_t key, BPTreeNode *parent) {
if (!root->is_leaf && !_BPTree_delete(traverse(root, key), key, root)) {
return false;
}
int index; // The data must also be stolen.
bool is_found = IntegerArray_binary_search(root->keys, key, &index); IntegerArray_append(node->data, sibling->data->items[0]);
if (root->is_leaf && !is_found) { IntegerArray_delete_at_index(sibling->data, 0);
return false;
} }
if (root->is_leaf) {
IntegerArray_delete_at_index(root->keys, index);
IntegerArray_delete_at_index(root->data, index);
} else if (is_found) {
root->keys->items[index] = find_smallest_key(root->children->items[index + 1]);
} }
if (parent == NULL && root->keys->size == 0) { static void steal_internal(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) {
shrink(root); int index_in_children = BPTreeNodeArray_search(parent->children, node);
}
if (parent != NULL && root->keys->size < root->order) { if (is_sibling_left_side(parent, node, sibling)) {
deletion_rebalance(root, parent); IntegerArray_insert_at_index(node->keys, 0, parent->keys->items[index_in_children - 1]);
parent->keys->items[index_in_children - 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[index_in_children]);
parent->keys->items[index_in_children] = 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);
} }
return true;
} }
bool BPTree_delete(BPTreeNode *root, uint64_t key) { static bool is_sibling_left_side(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) {
return _BPTree_delete(root, key, NULL); return BPTreeNodeArray_search(parent->children, sibling) < BPTreeNodeArray_search(parent->children, node);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment