diff --git a/main.c b/main.c new file mode 100644 index 0000000000000000000000000000000000000000..3d06a977a6157fa1876e319bbd047339f7b1133c --- /dev/null +++ b/main.c @@ -0,0 +1,157 @@ +#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[PHONE_NUMBER_MAXLEN]; + printf("Enter the phone number: "); + scanf("%10s", phone_number); + clear_buffer(); + + char name[NAME_MAXLEN]; + printf("Enter the name: "); + scanf("%20s", name); + clear_buffer(); + + char surname[SURNAME_MAXLEN]; + printf("Enter the surname: "); + scanf("%20s", surname); + clear_buffer(); + + int birth_date_year, birth_date_month, birth_date_day; + do { + printf("Enter the birth date (Y-m-d): "); + } while (scanf("%d-%d-%d", &birth_date_year, &birth_date_month, &birth_date_day) != 3); + + 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: "); + char phone_number[PHONE_NUMBER_MAXLEN]; + scanf("%10s", 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"); + } +} + +void delete_record(Directory *directory) { + printf("Enter the phone number that corresponds to the record you wish to delete: "); + + char phone_number[PHONE_NUMBER_MAXLEN]; + scanf("%10s", 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"); + + printf("\nAre you sure you want to delete this record? (Y/n) "); + + char choice = getchar(); + if (choice != '\n') { + getchar(); + } + + if (choice == 'n') { + printf("\n===>The procedure has been cancelled.\n"); + } else { + Directory_delete(directory, phone_number); + printf("Delete done\n"); + } + } +} + +int main() { + Directory *directory = Directory_init("directory_database"); + + while (true) { + BPTree_print(directory->index, 0); + + 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: + delete_record(directory); + 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/BPTree.c b/src/BPTree.c index ae2fd657b44c073a6c838a477175350d61d7a0d9..a6432e90cb59b91e1c60164371a1880ebcd833a4 100644 --- a/src/BPTree.c +++ b/src/BPTree.c @@ -7,34 +7,19 @@ #include "Array.h" -static bool has_maximum_keys(BPTreeNode *node); -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; - // CAUTION : 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]; - } +// BPTreeNode - return current; +static BPTreeNode *BPTreeNode_init(int order, bool is_leaf) { + BPTreeNode *root = (BPTreeNode *)malloc(sizeof(BPTreeNode)); + root->order = order; + root->is_leaf = is_leaf; + root->keys = IntegerArray_init(2 * root->order); + root->data = IntegerArray_init(2 * root->order); + root->children = BPTreeNodeArray_init(2 * root->order + 1); + root->next = NULL; + return root; } -// BPTreeNode - static void BPTreeNode_destroy(BPTreeNode **node) { IntegerArray_destroy(&(*node)->keys); IntegerArray_destroy(&(*node)->data); @@ -46,14 +31,7 @@ static void BPTreeNode_destroy(BPTreeNode **node) { // BPTree BPTreeNode *BPTree_init(int order) { - BPTreeNode *root = (BPTreeNode *)malloc(sizeof(BPTreeNode)); - root->order = order; - root->is_leaf = true; - root->keys = IntegerArray_init(2 * root->order); - root->data = IntegerArray_init(2 * root->order); - root->children = BPTreeNodeArray_init(2 * root->order + 1); - root->next = NULL; - return root; + return BPTreeNode_init(order, true); } void BPTree_destroy(BPTreeNode **root) { @@ -102,6 +80,18 @@ bool BPTree_search(BPTreeNode *root, uint64_t key, uint64_t *data) { return BPTree_search(root->children->items[child_index], key, data); } +// "traverse" function for insertion and deletion. + +static BPTreeNode *traverse(BPTreeNode *node, uint64_t key) { + int virtual_insertion_index = lower_bound(node->keys, key); + + 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]; +} + // BPTree : Insertion static void insert_non_full(BPTreeNode *node, uint64_t key, uint64_t data, BPTreeNode *previous_split_right_node) { @@ -119,47 +109,47 @@ static void insert_non_full(BPTreeNode *node, uint64_t key, uint64_t data, BPTre static void redistribute_keys(BPTreeNode *left_node, BPTreeNode *right_node, int left_index, int right_index) { for (int i = right_index; i < left_node->keys->size; i++) { IntegerArray_append(right_node->keys, left_node->keys->items[i]); - - if (left_node->is_leaf) { - IntegerArray_append(right_node->data, left_node->data->items[i]); - } } left_node->keys->size = left_index; - if (left_node->is_leaf) { + for (int i = right_index; i < left_node->data->size; i++) { + IntegerArray_append(right_node->data, left_node->data->items[i]); + } + + if (left_node->data->size > 0) { left_node->data->size = left_index; } } -static uint64_t split_leaf(BPTreeNode *node, uint64_t key, uint64_t data, BPTreeNode **right_node) { +static uint64_t split_leaf(BPTreeNode *node, uint64_t key, uint64_t data, BPTreeNode **split_right_node) { int virtual_insertion_index = lower_bound(node->keys, key); int median_index = node->keys->size / 2; uint64_t median_value; - *right_node = BPTree_init(node->order); + *split_right_node = BPTreeNode_init(node->order, true); if (virtual_insertion_index < median_index) { median_value = node->keys->items[median_index - 1]; - redistribute_keys(node, *right_node, median_index - 1, median_index - 1); + redistribute_keys(node, *split_right_node, median_index - 1, median_index - 1); int insertion_index = IntegerArray_insert_sorted(node->keys, key); IntegerArray_insert_at_index(node->data, insertion_index, data); } else if (virtual_insertion_index > median_index) { median_value = node->keys->items[median_index]; - redistribute_keys(node, *right_node, median_index, median_index); - int insertion_index = IntegerArray_insert_sorted((*right_node)->keys, key); - IntegerArray_insert_at_index((*right_node)->data, insertion_index, data); + redistribute_keys(node, *split_right_node, median_index, median_index); + int insertion_index = IntegerArray_insert_sorted((*split_right_node)->keys, key); + IntegerArray_insert_at_index((*split_right_node)->data, insertion_index, data); } else { median_value = key; - redistribute_keys(node, *right_node, median_index, median_index); - int insertion_index = IntegerArray_insert_sorted((*right_node)->keys, key); - IntegerArray_insert_at_index((*right_node)->data, insertion_index, data); + redistribute_keys(node, *split_right_node, median_index, median_index); + int insertion_index = IntegerArray_insert_sorted((*split_right_node)->keys, key); + IntegerArray_insert_at_index((*split_right_node)->data, insertion_index, data); } if (node->next != NULL) { - (*right_node)->next = node->next; + (*split_right_node)->next = node->next; } - node->next = *right_node; + node->next = *split_right_node; return median_value; } @@ -171,108 +161,98 @@ static void redistribute_children(BPTreeNode *left_node, BPTreeNode *right_node, left_node->children->size = left_index; } -static uint64_t split_internal(BPTreeNode *node, uint64_t key, BPTreeNode *right_child_node, BPTreeNode **right_node) { +static uint64_t split_internal(BPTreeNode *node, uint64_t key, BPTreeNode *previous_split_right_node, BPTreeNode **split_right_node) { int virtual_insertion_index = lower_bound(node->keys, key); int median_index = node->keys->size / 2; uint64_t median_value; - *right_node = BPTree_init(node->order); - (*right_node)->is_leaf = false; + *split_right_node = BPTreeNode_init(node->order, false); if (virtual_insertion_index < median_index) { median_value = node->keys->items[median_index - 1]; - redistribute_keys(node, *right_node, median_index - 1, median_index); - redistribute_children(node, *right_node, median_index, median_index); + redistribute_keys(node, *split_right_node, median_index - 1, median_index); + redistribute_children(node, *split_right_node, median_index, median_index); int insertion_index = IntegerArray_insert_sorted(node->keys, key); - BPTreeNodeArray_insert_at_index(node->children, insertion_index + 1, right_child_node); + BPTreeNodeArray_insert_at_index(node->children, insertion_index + 1, previous_split_right_node); } else if (virtual_insertion_index > median_index) { median_value = node->keys->items[median_index]; - redistribute_keys(node, *right_node, median_index, median_index + 1); - redistribute_children(node, *right_node, median_index + 1, median_index + 1); - int insertion_index = IntegerArray_insert_sorted((*right_node)->keys, key); - BPTreeNodeArray_insert_at_index((*right_node)->children, insertion_index + 1, right_child_node); + redistribute_keys(node, *split_right_node, median_index, median_index + 1); + redistribute_children(node, *split_right_node, median_index + 1, median_index + 1); + int insertion_index = IntegerArray_insert_sorted((*split_right_node)->keys, key); + BPTreeNodeArray_insert_at_index((*split_right_node)->children, insertion_index + 1, previous_split_right_node); } else { median_value = key; - redistribute_keys(node, *right_node, median_index, median_index); - redistribute_children(node, *right_node, median_index + 1, median_index + 1); - BPTreeNodeArray_insert_at_index((*right_node)->children, 0, right_child_node); + redistribute_keys(node, *split_right_node, median_index, median_index); + redistribute_children(node, *split_right_node, median_index + 1, median_index + 1); + BPTreeNodeArray_insert_at_index((*split_right_node)->children, 0, previous_split_right_node); } return median_value; } +static uint64_t insert_full(BPTreeNode *node, uint64_t key, uint64_t data, BPTreeNode *previous_split_right_node, BPTreeNode **split_right_node) { + if (node->is_leaf) { + return split_leaf(node, key, data, split_right_node); + } + + return split_internal(node, key, previous_split_right_node, split_right_node); +} + static void grow(BPTreeNode *root, uint64_t median_value, BPTreeNode *split_right_node) { - BPTreeNode *left_node = BPTree_init(root->order); - left_node->is_leaf = split_right_node->is_leaf; + BPTreeNode *left_node = BPTreeNode_init(root->order, split_right_node->is_leaf); root->is_leaf = false; IntegerArray_copy(root->keys, left_node->keys); - IntegerArray_clear(root->keys); - IntegerArray_append(root->keys, median_value); - IntegerArray_copy(root->data, left_node->data); - IntegerArray_clear(root->data); - BPTreeNodeArray_copy(root->children, left_node->children); + + IntegerArray_clear(root->keys); + IntegerArray_clear(root->data); BPTreeNodeArray_clear(root->children); + + IntegerArray_append(root->keys, median_value); BPTreeNodeArray_append(root->children, left_node); BPTreeNodeArray_append(root->children, split_right_node); } -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; +static bool _BPTree_insert(BPTreeNode *parent, BPTreeNode *root, uint64_t *key, uint64_t data, BPTreeNode **split_right_node) { + BPTreeNode *previous_split_right_node = NULL; + if (!root->is_leaf && !_BPTree_insert(root, traverse(root, *key), key, data, &previous_split_right_node)) { + return false; + } - if (node->is_leaf) { - median_value = split_leaf(node, key, data, &split_right_node); - } else { - median_value = split_internal(node, key, previous_split_right_node, &split_right_node); + int index; + bool is_found = IntegerArray_binary_search(root->keys, *key, &index); + if (root->is_leaf && is_found) { + return false; } - if (node == root) { - grow(root, median_value, split_right_node); - } else { - BPTreeNode *parent = BPTreeNodeArray_pop(parents); + if (!root->is_leaf && previous_split_right_node == NULL) { + *split_right_node = NULL; + return true; + } - if (has_maximum_keys(parent)) { - // 0 is passed instead of data because the recursion is necessarily done on an internal node. - insert_full(root, parents, parent, median_value, 0, split_right_node); - } else { - insert_non_full(parent, median_value, data, split_right_node); - } + if (root->keys->size < 2 * root->order) { + insert_non_full(root, *key, data, previous_split_right_node); + *split_right_node = NULL; + return true; } -} -void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) { - BPTreeNodeArray *parents; - BPTreeNode *leaf = find_leaf(root, key, &parents); + *key = insert_full(root, *key, data, previous_split_right_node, split_right_node); - int index; - if (IntegerArray_binary_search(leaf->keys, key, &index)) { - BPTreeNodeArray_destroy(&parents); - return; + if (parent == NULL) { + grow(root, *key, *split_right_node); } - if (has_maximum_keys(leaf)) { - insert_full(root, parents, leaf, key, data, NULL); - } else { - insert_non_full(leaf, key, data, NULL); - } + return true; +} - BPTreeNodeArray_destroy(&parents); +bool BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) { + BPTreeNode *previous_split_right_node; + return _BPTree_insert(NULL, root, &key, data, &previous_split_right_node); } // BPTree : Deletion -static BPTreeNode *traverse(BPTreeNode *node, uint64_t key) { - int virtual_insertion_index = lower_bound(node->keys, key); - - 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]; -} - static uint64_t find_smallest_key(BPTreeNode *root) { if (root->is_leaf) { return root->keys->items[0]; @@ -390,7 +370,7 @@ static void steal_internal(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sib } } -static void deletion_rebalance(BPTreeNode *node, BPTreeNode *parent) { +static void deletion_rebalance(BPTreeNode *parent, BPTreeNode *node) { BPTreeNode *sibling = find_sibling(parent, node); if (sibling->keys->size == sibling->order) { @@ -406,8 +386,8 @@ static void deletion_rebalance(BPTreeNode *node, BPTreeNode *parent) { } } -static bool _BPTree_delete(BPTreeNode *root, uint64_t key, BPTreeNode *parent) { - if (!root->is_leaf && !_BPTree_delete(traverse(root, key), key, root)) { +static bool _BPTree_delete(BPTreeNode *parent, BPTreeNode *root, uint64_t key) { + if (!root->is_leaf && !_BPTree_delete(root, traverse(root, key), key)) { return false; } @@ -429,12 +409,12 @@ static bool _BPTree_delete(BPTreeNode *root, uint64_t key, BPTreeNode *parent) { } if (parent != NULL && root->keys->size < root->order) { - deletion_rebalance(root, parent); + deletion_rebalance(parent, root); } return true; } bool BPTree_delete(BPTreeNode *root, uint64_t key) { - return _BPTree_delete(root, key, NULL); + return _BPTree_delete(NULL, root, key); } diff --git a/src/BPTree.h b/src/BPTree.h index 0c6bcb7297068d1ba4782e29c2fc90156b525757..762df82c58c8c579221ba4c9a7a33f29ecc2c6a4 100644 --- a/src/BPTree.h +++ b/src/BPTree.h @@ -20,7 +20,7 @@ void BPTree_destroy(BPTreeNode **root); void BPTree_print(BPTreeNode *root, int depth); bool BPTree_search(BPTreeNode *root, uint64_t key, uint64_t *data); -void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data); +bool BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data); bool BPTree_delete(BPTreeNode *root, uint64_t key); #endif diff --git a/src/main.c b/src/main.c index 3d06a977a6157fa1876e319bbd047339f7b1133c..8a634793edc7e623e38e985f8fb35994192c3ecd 100644 --- a/src/main.c +++ b/src/main.c @@ -1,157 +1,56 @@ -#include <stdio.h> +#include <assert.h> #include <stdlib.h> -#include "Directory.h" -#include "DirectoryRecord.h" +#include "Array.h" +#include "BPTree.h" -void clear_buffer() { - int c; - while ((c = getchar()) != '\n' && c != EOF) { - } -} - -void append_record(Directory *directory) { - char phone_number[PHONE_NUMBER_MAXLEN]; - printf("Enter the phone number: "); - scanf("%10s", phone_number); - clear_buffer(); - - char name[NAME_MAXLEN]; - printf("Enter the name: "); - scanf("%20s", name); - clear_buffer(); - - char surname[SURNAME_MAXLEN]; - printf("Enter the surname: "); - scanf("%20s", surname); - clear_buffer(); - - int birth_date_year, birth_date_month, birth_date_day; - do { - printf("Enter the birth date (Y-m-d): "); - } while (scanf("%d-%d-%d", &birth_date_year, &birth_date_month, &birth_date_day) != 3); - - 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: "); - char phone_number[PHONE_NUMBER_MAXLEN]; - scanf("%10s", phone_number); - clear_buffer(); - DirectoryRecord *record = Directory_search(directory, phone_number); - printf("\n"); +int main() { + BPTreeNode *root = BPTree_init(2); - if (record == NULL) { - printf("===>No records were found for this phone number.\n"); - } else { - printf("========================\n"); - DirectoryRecord_print(record); - DirectoryRecord_destroy(&record); - printf("========================\n"); + 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 delete_record(Directory *directory) { - printf("Enter the phone number that corresponds to the record you wish to delete: "); - - char phone_number[PHONE_NUMBER_MAXLEN]; - scanf("%10s", 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"); + IntegerArray_print(keys); - printf("\nAre you sure you want to delete this record? (Y/n) "); - - char choice = getchar(); - if (choice != '\n') { - getchar(); - } - - if (choice == 'n') { - printf("\n===>The procedure has been cancelled.\n"); - } else { - Directory_delete(directory, phone_number); - printf("Delete done\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) { - BPTree_print(directory->index, 0); - - 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: - delete_record(directory); - 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_delete(root, 5); + BPTree_delete(root, 8); + BPTree_delete(root, 21); + + BPTree_delete(root, 86); + BPTree_delete(root, 100); + BPTree_delete(root, 88); + BPTree_delete(root, 95); + BPTree_delete(root, 49); + BPTree_delete(root, 56); + BPTree_delete(root, 55); + + BPTree_print(root, 0); + + IntegerArray_destroy(&keys); + BPTree_destroy(&root); return EXIT_SUCCESS; } diff --git a/src/tests/BPTreeTests.c b/src/tests/BPTreeTests.c index 6c04c650a87caa6eb3b9721945c37be5edea2fe9..a6996d46cb72326f0666bd244bc93fb8a6360f5c 100644 --- a/src/tests/BPTreeTests.c +++ b/src/tests/BPTreeTests.c @@ -1,6 +1,12 @@ +/** + * @file BPTreeTests.c + * @author Florian Burgener (florian.burgener@etu.hesge.ch) + * @brief Unit tests of the BPTree data structure. + * @version 1.0 + * @date 2022-06-07 + */ #include <stdbool.h> #include <stdint.h> -#include <stdio.h> #include <stdlib.h> #include "../Array.h" @@ -10,18 +16,13 @@ #define RANDOM_MIN 0 #define RANDOM_MAX 1000 -BPTreeNode *tree; - -void setUp(void) { +void setUp() { } -void tearDown(void) { - if (tree != NULL) { - BPTree_destroy(&tree); - } +void tearDown() { } -// BEGIN : Compliance with B+ Tree rules +// BEGIN : Functions that check that a B+ Tree is compliant with the rules static BPTreeNode *find_first_leaf(BPTreeNode *root) { if (root->is_leaf) { @@ -218,7 +219,7 @@ static bool check_BPTree_compliance(BPTreeNode *root) { return is_compliant; } -// END : BPTree Compliance +// END : Functions that check that a B+ Tree is compliant with the rules /** * @brief Performs a linear search for an item in an array. @@ -271,7 +272,7 @@ static uint64_t transform_key_to_data(uint64_t key) { // **** BEGIN : test_BPTree_insert -static void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(BPTreeNode **root, int order) { +static void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(int order) { int size = 1; // Test 10 times, variable i being the seed. @@ -282,16 +283,16 @@ static void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_g // will have the size of 1 then 2, 4, 8, 16, 32, ... for (int j = 0; j < 8; j++) { IntegerArray *keys = generate_random_numbers_array(size, RANDOM_MIN, RANDOM_MAX); - *root = BPTree_init(order); + BPTreeNode *root = BPTree_init(order); for (int i = 0; i < keys->size; i++) { - BPTree_insert(*root, keys->items[i], transform_key_to_data(keys->items[i])); + BPTree_insert(root, keys->items[i], transform_key_to_data(keys->items[i])); // After each insertion is verified that the B+ Tree is compliant with the rules. - TEST_ASSERT(check_BPTree_compliance(*root)); + TEST_ASSERT(check_BPTree_compliance(root)); } IntegerArray_destroy(&keys); - BPTree_destroy(root); + BPTree_destroy(&root); size *= 2; } @@ -301,34 +302,34 @@ static void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_g } void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_order_1() { - test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 1); + test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(1); } void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_order_2() { - test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 2); + test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(2); } void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_order_3() { - test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 3); + test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(3); } void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_order_4() { - test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 4); + test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(4); } void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_order_8() { - test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 8); + test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(8); } void test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_order_16() { - test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 16); + test_BPTree_insert_should_comply_with_BPTree_rules_using_BPTree_of_given_order(16); } // **** END : test_BPTree_insert // **** BEGIN : test_BPTree_delete -void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(BPTreeNode **root, int order) { +void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(int order) { int size = 1; // Test 10 times, variable i being the seed. @@ -339,20 +340,20 @@ void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_or // will have the size of 1 then 2, 4, 8, 16, 32, ... for (int j = 0; j < 8; j++) { IntegerArray *keys = generate_random_numbers_array(size, RANDOM_MIN, RANDOM_MAX); - *root = BPTree_init(order); + BPTreeNode *root = BPTree_init(order); for (int i = 0; i < keys->size; i++) { - BPTree_insert(*root, keys->items[i], transform_key_to_data(keys->items[i])); + BPTree_insert(root, keys->items[i], transform_key_to_data(keys->items[i])); } while (keys->size > 0) { int index = rand() % keys->size; - BPTree_delete(*root, keys->items[index]); + BPTree_delete(root, keys->items[index]); IntegerArray_delete_at_index(keys, index); } IntegerArray_destroy(&keys); - BPTree_destroy(root); + BPTree_destroy(&root); size *= 2; } @@ -362,34 +363,34 @@ void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_or } void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_order_1() { - test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 1); + test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(1); } void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_order_2() { - test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 2); + test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(2); } void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_order_3() { - test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 3); + test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(3); } void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_order_4() { - test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 4); + test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(4); } void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_order_8() { - test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 8); + test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(8); } void test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_order_16() { - test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(&tree, 16); + test_BPTree_delete_should_comply_with_BPTree_rules_using_BPTree_of_given_order(16); } // **** END : test_BPTree_delete // **** BEGIN : test_BPTree_search -void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(BPTreeNode **root, int order) { +void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(int order) { int size = 256; // Test 10 times, variable i being the seed. @@ -397,47 +398,47 @@ void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTr srand(i); IntegerArray *keys = generate_random_numbers_array(size, RANDOM_MIN, RANDOM_MAX); - *root = BPTree_init(order); + BPTreeNode *root = BPTree_init(order); for (int i = 0; i < keys->size; i++) { - BPTree_insert(*root, keys->items[i], transform_key_to_data(keys->items[i])); + BPTree_insert(root, keys->items[i], transform_key_to_data(keys->items[i])); } for (int i = 0; i < keys->size; i++) { uint64_t data; - bool is_found = BPTree_search(*root, keys->items[i], &data); + bool is_found = BPTree_search(root, keys->items[i], &data); TEST_ASSERT(is_found); TEST_ASSERT_EQUAL_UINT64(transform_key_to_data(keys->items[i]), data); } IntegerArray_destroy(&keys); - BPTree_destroy(root); + BPTree_destroy(&root); } } void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_order_1() { - test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(&tree, 1); + test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(1); } void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_order_2() { - test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(&tree, 2); + test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(2); } void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_order_3() { - test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(&tree, 3); + test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(3); } void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_order_4() { - test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(&tree, 4); + test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(4); } void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_order_8() { - test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(&tree, 8); + test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(8); } void test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_order_16() { - test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(&tree, 16); + test_BPTree_search_should_find_the_keys_that_exist_in_the_BPTree_using_BPTree_of_given_order(16); } // **** END : test_BPTree_search