diff --git a/__main__.py b/__main__.py index e4d7be275907b2f0e7122281df9a5a7c0d32a966..3e10ac664f0ec2e8ee7d2a71411923985a8fcc98 100644 --- a/__main__.py +++ b/__main__.py @@ -470,7 +470,6 @@ def main(): root = Node(order) keys = generate_random_keys(30, 1, 99) print(keys) - print("=====") for key in keys: bptree_insert(root, key) diff --git a/a.b b/a.b deleted file mode 100644 index 70b5b9aff0b5af4f20193d014db73e020807bb84..0000000000000000000000000000000000000000 --- a/a.b +++ /dev/null @@ -1,37 +0,0 @@ -#include <assert.h> -// Warning : stdbool -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> - -#include "bptree.h" - -int main() { - BPTreeNode *root = bptree_init(2); - - uint64_t input[] = {8, 12, 11, 47, 22, 95, 86, 40, 33, 78, 28, 5, 75, 88, 21, 56, 82, 51, 93, 66, 48, 70, 57, 65, 35, 4, 60, 41, 49, 55, 68, 72, 23, 31, 30, 42, 18, 87, 24, 58}; - IntegerArray *keys = IntegerArray_init(40); - for (int i = 0; i < 40; i++) { - IntegerArray_append(keys, input[i]); - } - - IntegerArray_print(keys); - - for (int i = 0; i < keys->size; i++) { - bptree_insert(root, keys->items[i], keys->items[i] * 1000); - } - - bptree_print(root, 0); - - for (int i = 0; i < keys->size; i++) { - uint64_t data; - bool found = bptree_search(root, keys->items[i], &data); - - assert(found == true); - assert(data == keys->items[i] * 1000); - } - - IntegerArray_destroy(&keys); - bptree_destroy(&root); - return EXIT_SUCCESS; -} diff --git a/a.c b/a.c new file mode 100644 index 0000000000000000000000000000000000000000..29f74807e224eef5a79c94cd316e9e4eaa06002a --- /dev/null +++ b/a.c @@ -0,0 +1,123 @@ +// CAUTION : validation des entrées +#include <stdio.h> +#include <stdlib.h> + +#include "Directory.h" +#include "DirectoryRecord.h" + +void clear_buffer() { + int c; + while ((c = getchar()) != '\n' && c != EOF) { + } +} + +void append_record(Directory *directory) { + char phone_number[11]; + printf("Enter the phone number: "); + scanf("%s", phone_number); + clear_buffer(); + + char name[21]; + printf("Enter the name: "); + scanf("%s", name); + clear_buffer(); + + char surname[21]; + printf("Enter the surname: "); + scanf("%s", surname); + clear_buffer(); + + printf("Enter the birth date (Y-m-d): "); + // TODO : check more + int birth_date_year, birth_date_month, birth_date_day; + scanf("%d-%d-%d", &birth_date_year, &birth_date_month, &birth_date_day); + clear_buffer(); + + printf("\nIs the information entered correct? (Y/n) "); + + char choice = getchar(); + if (choice != '\n') { + getchar(); + } + + if (choice == 'n') { + printf("\n===>The procedure has been cancelled.\n"); + } else { + DirectoryRecord *record = DirectoryRecord_init(false, phone_number, name, surname, birth_date_year, birth_date_month, birth_date_day); + + if (Directory_append(directory, record)) { + printf("\n===>The record has been saved in the directory.\n"); + } else { + printf("\n===>This phone number is already associated with a record. The record has not been saved.\n"); + } + + DirectoryRecord_destroy(&record); + } +} + +void search_record(Directory *directory) { + printf("Enter the phone number that corresponds to the record you are looking for: "); + // TODO : crash phone number overflow + char phone_number[11]; + scanf("%s", phone_number); + clear_buffer(); + DirectoryRecord *record = Directory_search(directory, phone_number); + printf("\n"); + + if (record == NULL) { + printf("===>No records were found for this phone number.\n"); + } else { + printf("========================\n"); + DirectoryRecord_print(record); + DirectoryRecord_destroy(&record); + printf("========================\n"); + } +} + +int main() { + Directory *directory = Directory_init("directory_database"); + + while (true) { + printf("Enter 1 to add a member.\n"); + printf("Enter 2 to search for a member via their phone number.\n"); + printf("Enter 3 to delete a member.\n"); + printf("Enter 4 to display all members.\n"); + printf("Enter 5 to exit the program.\n"); + printf("What do you want to do? "); + int action; + scanf("%d", &action); + clear_buffer(); + + if (action < 1 || action > 5) { + system("clear"); + continue; + } + + if (action == 5) { + break; + } + + printf("\n"); + + switch (action) { + case 1: + append_record(directory); + break; + case 2: + search_record(directory); + break; + case 3: + break; + case 4: + Directory_print(directory); + break; + } + + printf("\nPress enter to continue..."); + getchar(); + system("clear"); + } + + Directory_destroy(&directory); + return EXIT_SUCCESS; +} diff --git a/src/Array.c b/src/Array.c index 9c7ca3f6dac21e92b67599191f784e3ca3ecf17d..4af759db9d2fd5369bbb10c2e14c3c2b6e67a1b0 100644 --- a/src/Array.c +++ b/src/Array.c @@ -89,17 +89,18 @@ bool IntegerArray_binary_search(IntegerArray *array, uint64_t item, int *index) } void IntegerArray_delete_at_index(IntegerArray *array, int index) { - for (int i = index; i < array->size; i++) { + for (int i = index; i < array->size - 1; i++) { array->items[i] = array->items[i + 1]; } array->size--; } -void IntegerArray_delete_sorted(IntegerArray *array, uint64_t item) { +int IntegerArray_delete_sorted(IntegerArray *array, uint64_t item) { int index; IntegerArray_binary_search(array, item, &index); IntegerArray_delete_at_index(array, index); + return index; } void IntegerArray_print(IntegerArray *array) { @@ -156,7 +157,7 @@ void BPTreeNodeArray_append(BPTreeNodeArray *array, BPTreeNode *item) { } void BPTreeNodeArray_delete_at_index(BPTreeNodeArray *array, int index) { - for (int i = index; i < array->size; i++) { + for (int i = index; i < array->size - 1; i++) { array->items[i] = array->items[i + 1]; } diff --git a/src/Array.h b/src/Array.h index 2c499f107d4baa21563770a47f9ae95a3a3a6340..895cbf4aa8c399c87c142fa1339cb161d67be3af 100644 --- a/src/Array.h +++ b/src/Array.h @@ -21,7 +21,7 @@ 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_at_index(IntegerArray *array, int index); -void IntegerArray_delete_sorted(IntegerArray *array, uint64_t item); +int 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 3bf98d450d7ae30c0488fd0c2913a3b408b521a3..5f454b37c6ba4d678d565c6923beed0d9b7e987b 100644 --- a/src/BPTree.c +++ b/src/BPTree.c @@ -35,6 +35,16 @@ static BPTreeNode *find_leaf(BPTreeNode *root, uint64_t key, BPTreeNodeArray **p // ======= +static void BPTreeNode_destroy(BPTreeNode **node) { + IntegerArray_destroy(&(*node)->keys); + IntegerArray_destroy(&(*node)->data); + BPTreeNodeArray_destroy(&(*node)->children); + free(*node); + *node = NULL; +} + +// ======= + BPTreeNode *BPTree_init(int order) { BPTreeNode *root = (BPTreeNode *)malloc(sizeof(BPTreeNode)); root->order = order; @@ -51,20 +61,21 @@ void BPTree_destroy(BPTreeNode **root) { BPTree_destroy(&(*root)->children->items[i]); } - IntegerArray_destroy(&(*root)->keys); - IntegerArray_destroy(&(*root)->data); - BPTreeNodeArray_destroy(&(*root)->children); - free(*root); - *root = NULL; + BPTreeNode_destroy(root); } void BPTree_print(BPTreeNode *root, int depth) { for (int i = 0; i < depth; i++) { printf(" "); } - IntegerArray_print(root->keys); + for (int i = 0; i < depth; i++) { + printf(" "); + } + printf("*"); + IntegerArray_print(root->data); + for (int i = 0; i < root->children->size; i++) { BPTree_print(root->children->items[i], depth + 1); } @@ -261,16 +272,14 @@ 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); 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 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 void _BPTree_delete(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNode *node, uint64_t key); @@ -300,15 +309,13 @@ 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); + IntegerArray_copy(child->data, root->data); BPTreeNodeArray_clear(root->children); BPTreeNodeArray_copy(child->children, root->children); - BPTreeNodeArray_clear(child->children); - BPTree_destroy(&child); + BPTreeNode_destroy(&child); } static void steal_internal(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling) { @@ -330,43 +337,58 @@ static void steal_internal(BPTreeNode *parent, BPTreeNode *node, int child_index 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_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; - IntegerArray_insert_at_index(node->keys, 0, 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 { uint64_t stealed_key = sibling->keys->items[0]; + IntegerArray_append(node->keys, stealed_key); IntegerArray_delete_at_index(sibling->keys, 0); parent->keys->items[child_index] = sibling->keys->items[0]; - IntegerArray_append(node->keys, stealed_key); + + // The data must also be stolen. + IntegerArray_append(node->data, sibling->data->items[0]); + IntegerArray_delete_at_index(sibling->data, 0); } } -static void _bptree_merge(BPTreeNode *parent, BPTreeNode *main_node, BPTreeNode *secondary_node, int pivot_index) { +static void _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]); } + // Merge the keys. 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]); - } + // Merge the data. + for (int i = secondary_node->data->size - 1; i >= 0; i--) { + IntegerArray_insert_at_index(main_node->data, 0, secondary_node->data->items[i]); + } + + // Merge the children. + 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); + + BPTreeNode_destroy(&secondary_node); } -static void bptree_merge(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) { +static void 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); + _merge(parent, node, sibling, child_index - 1); } else { - _bptree_merge(parent, sibling, node, child_index); + _merge(parent, sibling, node, child_index); } } @@ -401,7 +423,8 @@ static void _BPTree_delete(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNod } if (node->is_leaf) { - IntegerArray_delete_sorted(node->keys, key); + int index = IntegerArray_delete_sorted(node->keys, key); + IntegerArray_delete_at_index(node->data, index); } if (node != root && node->keys->size < node->order) { @@ -409,7 +432,7 @@ static void _BPTree_delete(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNod BPTreeNode *sibling = find_sibling(parent, node); if (sibling->keys->size == sibling->order) { - bptree_merge(parent, node, sibling); + merge(parent, node, sibling); if (parent == root && parent->keys->size == 0) { shrink(root); diff --git a/src/main.c b/src/main.c index 29f74807e224eef5a79c94cd316e9e4eaa06002a..fde343156b3b669c1bb6c1e8c70669dcac0bd2e3 100644 --- a/src/main.c +++ b/src/main.c @@ -1,123 +1,46 @@ -// CAUTION : validation des entrées +#include <assert.h> +// Warning : stdbool +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include "Directory.h" -#include "DirectoryRecord.h" +#include "BPTree.h" -void clear_buffer() { - int c; - while ((c = getchar()) != '\n' && c != EOF) { - } -} - -void append_record(Directory *directory) { - char phone_number[11]; - printf("Enter the phone number: "); - scanf("%s", phone_number); - clear_buffer(); - - char name[21]; - printf("Enter the name: "); - scanf("%s", name); - clear_buffer(); - - char surname[21]; - printf("Enter the surname: "); - scanf("%s", surname); - clear_buffer(); - - printf("Enter the birth date (Y-m-d): "); - // TODO : check more - int birth_date_year, birth_date_month, birth_date_day; - scanf("%d-%d-%d", &birth_date_year, &birth_date_month, &birth_date_day); - clear_buffer(); - - printf("\nIs the information entered correct? (Y/n) "); - - char choice = getchar(); - if (choice != '\n') { - getchar(); - } - - if (choice == 'n') { - printf("\n===>The procedure has been cancelled.\n"); - } else { - DirectoryRecord *record = DirectoryRecord_init(false, phone_number, name, surname, birth_date_year, birth_date_month, birth_date_day); - - if (Directory_append(directory, record)) { - printf("\n===>The record has been saved in the directory.\n"); - } else { - printf("\n===>This phone number is already associated with a record. The record has not been saved.\n"); - } +int main() { + BPTreeNode *root = BPTree_init(2); - DirectoryRecord_destroy(&record); + uint64_t input[] = {8, 12, 11, 47, 22, 95, 86, 40, 33, 78, 28, 5, 75, 88, 21, 56, 82, 51, 93, 66, 48, 70, 57, 65, 35, 4, 60, 41, 49, 55, 68, 72, 23, 31, 30, 42, 18, 87, 24, 58}; + IntegerArray *keys = IntegerArray_init(40); + for (int i = 0; i < 30; i++) { + IntegerArray_append(keys, input[i]); } -} -void search_record(Directory *directory) { - printf("Enter the phone number that corresponds to the record you are looking for: "); - // TODO : crash phone number overflow - char phone_number[11]; - scanf("%s", phone_number); - clear_buffer(); - DirectoryRecord *record = Directory_search(directory, phone_number); - printf("\n"); + IntegerArray_print(keys); - if (record == NULL) { - printf("===>No records were found for this phone number.\n"); - } else { - printf("========================\n"); - DirectoryRecord_print(record); - DirectoryRecord_destroy(&record); - printf("========================\n"); + for (int i = 0; i < keys->size; i++) { + BPTree_insert(root, keys->items[i], keys->items[i] * 1000); } -} - -int main() { - Directory *directory = Directory_init("directory_database"); - - while (true) { - printf("Enter 1 to add a member.\n"); - printf("Enter 2 to search for a member via their phone number.\n"); - printf("Enter 3 to delete a member.\n"); - printf("Enter 4 to display all members.\n"); - printf("Enter 5 to exit the program.\n"); - printf("What do you want to do? "); - int action; - scanf("%d", &action); - clear_buffer(); - - if (action < 1 || action > 5) { - system("clear"); - continue; - } - - if (action == 5) { - break; - } - - printf("\n"); - switch (action) { - case 1: - append_record(directory); - break; - case 2: - search_record(directory); - break; - case 3: - break; - case 4: - Directory_print(directory); - break; - } + for (int i = 0; i < keys->size; i++) { + uint64_t data; + bool found = BPTree_search(root, keys->items[i], &data); - printf("\nPress enter to continue..."); - getchar(); - system("clear"); + assert(found == true); + assert(data == keys->items[i] * 1000); } - Directory_destroy(&directory); + BPTree_delete(root, 65); + BPTree_delete(root, 57); + BPTree_delete(root, 47); + BPTree_delete(root, 28); + BPTree_delete(root, 51); + BPTree_insert(root, 100, 100 * 1000); + BPTree_delete(root, 48); + BPTree_delete(root, 41); + BPTree_delete(root, 60); + BPTree_print(root, 0); + + IntegerArray_destroy(&keys); + BPTree_destroy(&root); return EXIT_SUCCESS; }