diff --git a/bp_tree.c b/bp_tree.c index f7a3ab800ba13700808c0791e0a2f90555ebaafb..493af2ea442e67efc29dc53ade24b29d0f6423ba 100644 --- a/bp_tree.c +++ b/bp_tree.c @@ -1,26 +1,21 @@ #include "bp_tree.h" +#include <math.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <stdbool.h> -#include <math.h> -typedef struct control{ +typedef struct control { int value; node *lhs; node *rhs; -}control; +} control; -const control CONST_CONTR = { - .value = 0, - .lhs = NULL, - .rhs = NULL -}; +const control CONST_CONTR = {.value = 0, .lhs = NULL, .rhs = NULL}; -node* bp_create_node() -{ +node *bp_create_node() { node *nd = malloc(sizeof(node)); - for (int i = 0; i < M+1; i++) + for (int i = 0; i < M + 1; i++) nd->childs[i] = NULL; for (int i = 0; i < M; i++) nd->data[i] = 0; @@ -29,77 +24,71 @@ node* bp_create_node() return nd; } -control value_to_insert(int val) -{ +control value_to_insert(int val) { control c; c.value = val; c.lhs = c.rhs = NULL; return c; } -bool bp_is_leaf(node *nd) {return nd->childs[0] == NULL;} +bool bp_is_leaf(node *nd) { return nd->childs[0] == NULL; } -void bp_node_shift(node *nd, int index) -{ - // as there is one more child than values, we must do one more iteration outside of the for - nd->childs[M] = nd->childs[M-1]; +void bp_node_shift(node *nd, int index) { + // as there is one more child than values, we must do one more iteration + // outside of the for + nd->childs[M] = nd->childs[M - 1]; - for (int i = M-1; i > index; i--) - { - nd->data[i] = nd->data[i-1]; - nd->childs[i+1] = nd->childs[i]; + for (int i = M - 1; i > index; i--) { + nd->data[i] = nd->data[i - 1]; + nd->childs[i + 1] = nd->childs[i]; } } -node* bp_split(node *nd) -{ +node *bp_split(node *nd) { node *new = bp_create_node(); /* this weird thing is for the for loop up to how many loop do we want to do - we need it outside because if the order of the tree is odd, we must do one more loop + we need it outside because if the order of the tree is odd, we must do + one more loop */ - int upto = (int)floor(M/2); + int upto = (int)floor(M / 2); int index = upto; // update the new counts - nd->count = (int)floor(nd->count/2); + nd->count = (int)floor(nd->count / 2); new->count = upto; // as explained, do shit if the order is odd - if (M%2 == 1) - { + if (M % 2 == 1) { upto++; - new->count++; + new->count++; } - for (int i = 0; i < upto; i++) - { + for (int i = 0; i < upto; i++) { new->data[i] = nd->data[index + i]; nd->data[index + i] = 0; new->childs[i] = nd->childs[index + i]; nd->childs[index + i] = NULL; } - + return new; } -control bp_insert_into(node *nd, control val) -{ - // look for a 0 in the node (it is guarenteed to exist in this version of the algorithm) - for (int i = 0; i < M; i++) - { +control bp_insert_into(node *nd, control val) { + // look for a 0 in the node (it is guarenteed to exist in this version of + // the algorithm) + for (int i = 0; i < M; i++) { // if we plainly find a 0 - if (nd->data[i] == 0) - { + if (nd->data[i] == 0) { nd->data[i] = val.value; nd->childs[i] = val.lhs; break; } - // if we need to insert the value between two values, we need to shifter everything greater than our value one case further - if (nd->data[i] > val.value) - { + // if we need to insert the value between two values, we need to + // shifter everything greater than our value one case further + if (nd->data[i] > val.value) { bp_node_shift(nd, i); nd->data[i] = val.value; nd->childs[i] = val.rhs; @@ -109,15 +98,15 @@ control bp_insert_into(node *nd, control val) nd->count++; // if the node is now full, we split - if (nd->count == M) - { + if (nd->count == M) { control v; node *new = bp_split(nd); v.lhs = nd; v.rhs = new; v.value = new->data[0]; - // if the new node we created is a leaf, we must add it to the linked list + // if the new node we created is a leaf, we must add it to the + // linked list if (bp_is_leaf(new)) nd->next = new; @@ -126,82 +115,87 @@ control bp_insert_into(node *nd, control val) return CONST_CONTR; } -control bp_insert(node *nd, control val){ - control c; // will help us to return the pivot, and the two pointers of the childs-to-be - +control bp_insert(node *nd, control val) { + control c; // will help us to return the pivot, and the two pointers of the + // childs-to-be + // if we are in a leaf, we found where to insert the value, so let's do it if (bp_is_leaf(nd)) c = bp_insert_into(nd, val); else // otherwise let's keep looking { - for (int i = 0; i < M; i++) - { - if (nd->data[i] > val.value || nd->data[i] == 0) - { + for (int i = 0; i < M; i++) { + if (nd->data[i] > val.value || nd->data[i] == 0) { c = bp_insert(nd->childs[i], val); break; } } } // if a split happened - if (c.value != 0) - { + if (c.value != 0) { return c; } return CONST_CONTR; } -node* bp_split_root(node *root) -{ +node *bp_split_root(node *root) { // TEMPORARY FUNC (COPYRIGHT), HARD WRITTEN NEEDS TO BE SOFT node *new = bp_create_node(); - node *rhs = bp_create_node(); + node *rhs = bp_create_node(); - rhs->childs[0] = root->childs[3]; - rhs->childs[1] = root->childs[4]; - - root->childs[3] = NULL; - root->childs[4] = NULL; - - rhs->data[0] = root->data[3]; - root->data[3] = 0; + int index = (int)floor(M / 2); + + int looper = index; + if (M % 2 == 0) { + looper--; + } + + for (int i = 0; i <= looper; i++) { + rhs->childs[i] = root->childs[index + i + 1]; + root->childs[index + i + 1] = NULL; + } + + for (int i = 0; i < looper; i++) { + rhs->data[i] = root->data[index + i + 1]; + root->data[index + i + 1] = 0; + } new->childs[0] = root; new->childs[1] = rhs; - new->data[0] = root->data[2]; + new->data[0] = root->data[index]; - root->data[2] = 0; + root->data[index] = 0; new->count = 1; - root->count = M/2; - rhs->count = M/2; + root->count = index; + rhs->count = index; + if (M % 2 == 0) { + rhs->count--; + } return new; } -node* bp_insert_val(node* tree, int val) -{ +node *bp_insert_val(node *tree, int val) { // Parse the val into a control struct then insert it in the tree control test = bp_insert(tree, value_to_insert(val)); /* depending on the control item, we act differently - if the control has pointers to node, then we had a split in the direct childs of the root. We must add the values upringed to the root + if the control has pointers to node, then we had a split in the direct + childs of the root. We must add the values upringed to the root */ - if ( test.rhs != NULL) - { - /* + if (test.rhs != NULL) { + /* if the root isn't a leaf, first we add the value into the node - we can't use bp_insert_into() as if we need a split, the way we do it is slightly different + we can't use bp_insert_into() as if we need a split, the way we + do it is slightly different */ - if (!bp_is_leaf(tree)) - { - for (int i = 0; i < M; i++) - { - if (tree->data[i] == 0) - { - tree->childs[i+1] = test.rhs; + if (!bp_is_leaf(tree)) { + for (int i = 0; i < M; i++) { + if (tree->data[i] == 0) { + tree->childs[i + 1] = test.rhs; tree->data[i] = test.value; tree->count++; break; @@ -209,16 +203,16 @@ node* bp_insert_val(node* tree, int val) } // If the root is full, we must split it - if (tree->count == M) - { + if (tree->count == M) { return bp_split_root(tree); } - //if not, we can simply return the root + // if not, we can simply return the root return tree; } - - // if, after a split, the root was a leaf, we must create a new node which will contain the values from the control + + // if, after a split, the root was a leaf, we must create a new + // node which will contain the values from the control tree = bp_create_node(); tree->childs[0] = test.lhs; tree->childs[1] = test.rhs; @@ -228,16 +222,13 @@ node* bp_insert_val(node* tree, int val) return tree; } -void bp_destroy(node *root) -{ +void bp_destroy(node *root) { if (root == NULL) return; - + // free the childs first - if (!bp_is_leaf(root)) - { - for (int i = 0; i < M; i++) - { + if (!bp_is_leaf(root)) { + for (int i = 0; i < M; i++) { bp_destroy(root->childs[i]); } } @@ -246,63 +237,54 @@ void bp_destroy(node *root) free(root); } -void bp_print_as_ll(node *root) -{ +void bp_print_as_ll(node *root) { // if we reached the end of the list - if (root == NULL) - { + if (root == NULL) { printf("NULL\n"); return; } - + // search for the first leaf on the tree - if (!bp_is_leaf(root)) - { + if (!bp_is_leaf(root)) { return bp_print_as_ll(root->childs[0]); } - + printf("|"); - // print every values in the node until hitting 0, then we can get on the next node - for (int i = 0; i < M; i++) - { + // print every values in the node until hitting 0, then we can get on the + // next node + for (int i = 0; i < M; i++) { printf(" %d |", root->data[i]); - if (root->data[i+1] == 0) - { + if (root->data[i + 1] == 0) { printf(" -> "); return bp_print_as_ll(root->next); } } - } -void bp_print(node *root, int depth) -{ +void bp_print(node *root, int depth) { // if we are on a leaf, we can print the values directly next to each other - if (bp_is_leaf(root)) - { + if (bp_is_leaf(root)) { for (int i = 0; i < depth; i++) printf(" "); - for (int i = 0; i < M; i++) - { + for (int i = 0; i < M; i++) { printf(" %d |", root->data[i]); // if we reach a 0, we have seen every values in the node - if (root->data[i+1] == 0) + if (root->data[i + 1] == 0) break; } return; } - for (int i = 0; i < M; i++) - { + for (int i = 0; i < M; i++) { bp_print(root->childs[i], depth + 1); printf("\n"); - + for (int i = 0; i < depth; i++) printf(" "); - + printf(" %d |\n", root->data[i]); - if (root->data[i+1] == 0) - return bp_print(root->childs[i+1], depth + 1); + if (root->data[i + 1] == 0) + return bp_print(root->childs[i + 1], depth + 1); } } \ No newline at end of file diff --git a/bp_tree.h b/bp_tree.h index 95cce5de883c810675d5983a790d846e30388034..74c769d5d8b94e3c9ef6e5c294b3f9ee8143fa3a 100644 --- a/bp_tree.h +++ b/bp_tree.h @@ -4,32 +4,48 @@ #define M 4 #include <stdlib.h> -typedef struct node{ - struct node *childs[M+1]; +typedef struct node { + struct node *childs[M + 1]; int data[M]; int count; struct node *next; -}node; +} node; -/// @short Print in CLI a B+ Tree -/// @param *root Root of the tree to print -/// @param depth Always set as 0 +/** + * @brief Print in CLI a B+ Tree + * + * @param root Root of the tree to print + * @param depth Always set as 0 + */ void bp_print(node *root, int depth); -/// @short Free an entire B+ Tree -/// @param *root pointer to the root of the tree to free +/** + * @brief Free an entire B+ Tree + * + * @param root pointer to the root of the tree to free + */ void bp_destroy(node *root); -/// @short Creates a new node of a tree with every values set in a known way -/// @return Pointer to new node created -node* bp_create_node(); +/** + * @brief Creates a new node of a tree with every values set in a known way + * + * @return Pointer to new node created + */ +node *bp_create_node(); -/// @short Insert a new int (key) into a B+ Tree -/// @param *tree Pointer of the root of the tree -/// @param val Value to insert -node* bp_insert_val(node* tree, int val); +/** + * @brief Insert a new int (key) into a B+ Tree + * + * @param tree Pointer of the root of the tree + * @param val Value to insert + * @return New root of the tree + */ +node *bp_insert_val(node *tree, int val); -/// @short Print in CLI the leaves of the B+ Tree as a linked list -/// @param *root Pointer to the root of the tree to print +/** + * @brief Print in CLI the leaves of the B+ Tree as a linked list + * + * @param root Pointer to the root of the tree to print + */ void bp_print_as_ll(node *root); #endif diff --git a/main.c b/main.c index 5ac9fee2b50eee95699dec9c100a08fb94b7fbfe..e2a7543dcc8e9bb508b1875bee33fb6beb4fd1b0 100644 --- a/main.c +++ b/main.c @@ -2,42 +2,49 @@ #include <stdio.h> #include <stdlib.h> -int -main () -{ - node *tree = bp_create_node (); +int main() { + node *tree = bp_create_node(); - tree = bp_insert_val (tree, 3); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 6); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 5); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 4); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 7); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 8); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 9); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 10); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 11); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - tree = bp_insert_val (tree, 12); - bp_print (tree, 0); - printf ("\n|||||||||\n"); - bp_print_as_ll (tree); - bp_destroy (tree); - return 0; + tree = bp_insert_val(tree, 3); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 6); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 5); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 4); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 7); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 8); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 9); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 10); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 11); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 12); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 13); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 14); + bp_print(tree, 0); + printf("\n|||||||||\n"); + tree = bp_insert_val(tree, 15); + bp_print(tree, 0); + printf("\n|||||||||\n"); + bp_print_as_ll(tree); + bp_destroy(tree); + return 0; } \ No newline at end of file