diff --git a/src/Array.c b/src/Array.c index c6a437e543813f7c5599e79ec4f745bbc9f962c8..9c7ca3f6dac21e92b67599191f784e3ca3ecf17d 100644 --- a/src/Array.c +++ b/src/Array.c @@ -39,6 +39,7 @@ void IntegerArray_destroy(IntegerArray **array) { int IntegerArray_insert_sorted(IntegerArray *array, uint64_t item) { int index = lower_bound(array, item); + // TODO : use IntegerArray_insert_at_index for (int i = array->size - 1; i >= index; i--) { array->items[i + 1] = array->items[i]; @@ -95,6 +96,12 @@ void IntegerArray_delete_at_index(IntegerArray *array, int index) { array->size--; } +void IntegerArray_delete_sorted(IntegerArray *array, uint64_t item) { + int index; + IntegerArray_binary_search(array, item, &index); + IntegerArray_delete_at_index(array, index); +} + void IntegerArray_print(IntegerArray *array) { printf("["); diff --git a/src/Array.h b/src/Array.h index 99f19602017854ee6fc9affabb16e15985470d5e..2c499f107d4baa21563770a47f9ae95a3a3a6340 100644 --- a/src/Array.h +++ b/src/Array.h @@ -20,8 +20,8 @@ int IntegerArray_insert_sorted(IntegerArray *array, uint64_t item); void IntegerArray_insert_at_index(IntegerArray *array, int index, uint64_t item); void IntegerArray_append(IntegerArray *array, uint64_t item); bool IntegerArray_binary_search(IntegerArray *array, uint64_t item, int *index); -void IntegerArray_delete_sorted(IntegerArray *array, uint64_t item); void IntegerArray_delete_at_index(IntegerArray *array, int index); +void IntegerArray_delete_sorted(IntegerArray *array, uint64_t item); void IntegerArray_print(IntegerArray *array); void IntegerArray_clear(IntegerArray *array); void IntegerArray_copy(IntegerArray *src, IntegerArray *dest); diff --git a/src/BPTree.c b/src/BPTree.c index de6852a35e1423d5cbeee3cc3675f732ba0f4de9..3bf98d450d7ae30c0488fd0c2913a3b408b521a3 100644 --- a/src/BPTree.c +++ b/src/BPTree.c @@ -7,17 +7,34 @@ #include "Array.h" -// static bool has_minimum_keys(BPTreeNode *node); static bool has_maximum_keys(BPTreeNode *node); - -// static bool has_minimum_keys(BPTreeNode *node) { -// return node->keys_length == node->order; -// } +static BPTreeNode *find_leaf(BPTreeNode *root, uint64_t key, BPTreeNodeArray **parents); static bool has_maximum_keys(BPTreeNode *node) { return node->keys->size == 2 * node->order; } +static BPTreeNode *find_leaf(BPTreeNode *root, uint64_t key, BPTreeNodeArray **parents) { + BPTreeNode *current = root; + // TODO : 10 is not enough. + *parents = BPTreeNodeArray_init(10); + + while (!current->is_leaf) { + BPTreeNodeArray_append(*parents, current); + int child_index = lower_bound(current->keys, key); + + if (child_index < current->keys->size && current->keys->items[child_index] == key) { + child_index += 1; + } + + current = current->children->items[child_index]; + } + + return current; +} + +// ======= + BPTreeNode *BPTree_init(int order) { BPTreeNode *root = (BPTreeNode *)malloc(sizeof(BPTreeNode)); root->order = order; @@ -81,7 +98,6 @@ static void redistribute_children(BPTreeNode *left_node, BPTreeNode *right_node, static uint64_t split_internal(BPTreeNode *node, uint64_t key, BPTreeNode *right_child_node, BPTreeNode **right_node); static uint64_t split_leaf(BPTreeNode *node, uint64_t key, uint64_t data, BPTreeNode **right_node); static void grow(BPTreeNode *root, uint64_t median_value, BPTreeNode *split_right_node); -static BPTreeNode *find_leaf(BPTreeNode *root, uint64_t key, BPTreeNodeArray **parents); static void insert_full(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNode *node, uint64_t key, uint64_t data, BPTreeNode *previous_split_right_node); static void insert_non_full(BPTreeNode *node, uint64_t key, uint64_t data, BPTreeNode *previous_split_right_node); @@ -187,25 +203,6 @@ static void grow(BPTreeNode *root, uint64_t median_value, BPTreeNode *split_righ BPTreeNodeArray_append(root->children, split_right_node); } -static BPTreeNode *find_leaf(BPTreeNode *root, uint64_t key, BPTreeNodeArray **parents) { - BPTreeNode *current = root; - // TODO : 10 is not enough. - *parents = BPTreeNodeArray_init(10); - - while (!current->is_leaf) { - BPTreeNodeArray_append(*parents, current); - int child_index = lower_bound(current->keys, key); - - if (child_index < current->keys->size && current->keys->items[child_index] == key) { - child_index += 1; - } - - current = current->children->items[child_index]; - } - - return current; -} - static void insert_full(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNode *node, uint64_t key, uint64_t data, BPTreeNode *previous_split_right_node) { uint64_t median_value; BPTreeNode *split_right_node; @@ -247,7 +244,11 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) { BPTreeNodeArray *parents; BPTreeNode *leaf = find_leaf(root, key, &parents); - // TODO : vérifier si la clé existe dans leaf. + int index; + if (IntegerArray_binary_search(leaf->keys, key, &index)) { + BPTreeNodeArray_destroy(&parents); + return; + } if (has_maximum_keys(leaf)) { insert_full(root, parents, leaf, key, data, NULL); @@ -260,6 +261,8 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) { // Deletion +// CAUTION : data is not processed + 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); @@ -269,8 +272,9 @@ static void steal_leaf(BPTreeNode *parent, BPTreeNode *node, int child_index, BP 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 void _BPTree_delete(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNode *node, uint64_t key); - static uint64_t find_smallest_key(BPTreeNode *root) { +static uint64_t find_smallest_key(BPTreeNode *root) { if (root->is_leaf) { return root->keys->items[0]; } @@ -388,9 +392,58 @@ static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node) { return parent->children->items[child_index - 1]; } -static void _bptree_delete(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNode *node, uint64_t key) { +static void _BPTree_delete(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNode *node, uint64_t key) { BPTreeNode *parent = NULL; + + if (parents->size > 0) { + parent = parents->items[parents->size - 1]; + BPTreeNodeArray_delete_at_index(parents, parents->size - 1); + } + + if (node->is_leaf) { + IntegerArray_delete_sorted(node->keys, key); + } + + if (node != root && node->keys->size < node->order) { + int child_index = find_child_index(parent, node); + BPTreeNode *sibling = find_sibling(parent, node); + + if (sibling->keys->size == sibling->order) { + bptree_merge(parent, node, sibling); + + if (parent == root && parent->keys->size == 0) { + shrink(root); + parent = NULL; + } + } else { + if (node->is_leaf) { + steal_leaf(parent, node, child_index, sibling); + } else { + steal_internal(parent, node, child_index, sibling); + } + } + } + + int index; + if (!node->is_leaf && node->children->size > 0 && IntegerArray_binary_search(node->keys, key, &index)) { + node->keys->items[index] = find_smallest_key(node->children->items[index + 1]); + } + + if (parent != NULL) { + _BPTree_delete(root, parents, parent, key); + } } void BPTree_delete(BPTreeNode *root, uint64_t key) { + BPTreeNodeArray *parents; + BPTreeNode *leaf = find_leaf(root, key, &parents); + + int index; + if (!IntegerArray_binary_search(leaf->keys, key, &index)) { + BPTreeNodeArray_destroy(&parents); + return; + } + + _BPTree_delete(root, parents, leaf, key); + BPTreeNodeArray_destroy(&parents); }