diff --git a/bp_tree.c b/bp_tree.c index 248423afbb9e3aadfac3ae2a7f0b3421fd2fffbe..9c94ef736a6b72ac68e68432606cf376c0cf9470 100644 --- a/bp_tree.c +++ b/bp_tree.c @@ -4,6 +4,12 @@ #include <stdbool.h> #include <math.h> +typedef struct control{ + int value; + node *lhs; + node *rhs; +}control; + const control CONST_CONTR = { .value = 0, .lhs = NULL, @@ -35,7 +41,9 @@ 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]; + for (int i = M-1; i > index; i--) { nd->data[i] = nd->data[i-1]; @@ -46,28 +54,50 @@ void bp_node_shift(node *nd, int index) node* bp_split(node *nd) { node *new = bp_create_node(); - for (int i = 0; i < M/2; i++) + /* + 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 + */ + int upto = (int)floor(M/2); + int index = upto; + + // update the new counts + nd->count = (int)floor(nd->count/2); + new->count = upto; + + // as explained, do shit if the order is odd + if (M%2 == 1) + { + upto++; + new->count++; + } + + for (int i = 0; i < upto; i++) { - new->data[i] = nd->data[M/2 + i]; - nd->data[M/2 + i] = 0; - new->childs[i] = nd->childs[M/2 + i]; - nd->childs[M/2 + i] = NULL; + new->data[i] = nd->data[index + i]; + nd->data[index + i] = 0; + new->childs[i] = nd->childs[index + i]; + nd->childs[index + i] = NULL; } - nd->count /=2; - new->count = M/2; + 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++) { + // if we plainly find a 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) { bp_node_shift(nd, i); @@ -78,7 +108,7 @@ control bp_insert_into(node *nd, control val) } nd->count++; - + // if the node is now full, we split if (nd->count == M) { control v; @@ -86,20 +116,23 @@ control bp_insert_into(node *nd, control val) 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 (bp_is_leaf(new)) nd->next = new; + return v; } return CONST_CONTR; } control bp_insert(node *nd, control val){ - control c; + 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 + else // otherwise let's keep looking { for (int i = 0; i < M; i++) { @@ -109,9 +142,8 @@ control bp_insert(node *nd, control val){ break; } } - //c = bp_insert_into(nd, c); } - // Si il y a eu un split + // if a split happened if (c.value != 0) { return c; @@ -121,6 +153,7 @@ control bp_insert(node *nd, control val){ 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(); @@ -147,12 +180,21 @@ node* bp_split_root(node *root) return new; } - 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 ( 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 + */ if (!bp_is_leaf(tree)) { for (int i = 0; i < M; i++) @@ -166,16 +208,17 @@ node* bp_insert_val(node* tree, int val) } } - /* GROS ICI SI LA RACINE N'EST PAS UNE FEUILLE ET QU'APRES AVOIR REMONTE UNE VALEUR LA RACINE EST PLEINE, IL FAUT SPLIT LA RACINE */ - printf("%d\n", tree->count); + // If the root is full, we must split it if (tree->count == M) { return bp_split_root(tree); } + //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 tree = bp_create_node(); tree->childs[0] = test.lhs; tree->childs[1] = test.rhs; @@ -185,58 +228,64 @@ node* bp_insert_val(node* tree, int val) return tree; } -void bp_destroy(node *nd) +void bp_destroy(node *root) { - if (nd == NULL) + if (root == NULL) return; - if (!bp_is_leaf(nd)) + // free the childs first + if (!bp_is_leaf(root)) { for (int i = 0; i < M; i++) { - bp_destroy(nd->childs[i]); + bp_destroy(root->childs[i]); } } - //free(nd->childs); - free(nd); -} + // then free the root + free(root); +} -void bp_print_as_ll(node *nd) +void bp_print_as_ll(node *root) { - if (nd == NULL) + // if we reached the end of the list + if (root == NULL) { printf("NULL\n"); return; } - if (!bp_is_leaf(nd)) + // search for the first leaf on the tree + if (!bp_is_leaf(root)) { - return bp_print_as_ll(nd->childs[0]); + return bp_print_as_ll(root->childs[0]); } + // 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 |", nd->data[i]); - if (nd->data[i+1] == 0) + printf(" %d |", root->data[i]); + if (root->data[i+1] == 0) { printf("->"); - return bp_print_as_ll(nd->next); + return bp_print_as_ll(root->next); } } } -void bp_print(node *nd, int depth) +void bp_print(node *root, int depth) { - if (bp_is_leaf(nd)) + // if we are on a leaf, we can print the values directly next to each other + if (bp_is_leaf(root)) { for (int i = 0; i < depth; i++) printf(" "); for (int i = 0; i < M; i++) { - printf(" %d |", nd->data[i]); - if (nd->data[i+1] == 0) + printf(" %d |", root->data[i]); + // if we reach a 0, we have seen every values in the node + if (root->data[i+1] == 0) break; } printf("\n"); @@ -244,19 +293,18 @@ void bp_print(node *nd, int depth) } for (int i = 0; i < M; i++) - { - + { printf("\n"); - bp_print(nd->childs[i], depth + 1); + bp_print(root->childs[i], depth + 1); for (int i = 0; i < depth; i++) printf(" "); - printf(" %d |", nd->data[i]); + printf(" %d |", root->data[i]); - if (nd->data[i+1] == 0) + if (root->data[i+1] == 0) { printf("\n"); - return bp_print(nd->childs[i+1], depth + 1); + 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 bd8bccfa498e92e3bfa25d71efca8c2e7cab02ed..93a16b98cd9f5f7d92bf34a596856fa2f105ba82 100644 --- a/bp_tree.h +++ b/bp_tree.h @@ -1,7 +1,7 @@ #ifndef _BP_TREE_C_ #define _BP_TREE_C_ -#define M 4 +#define M 5 #include <stdlib.h> typedef struct node{ @@ -11,17 +11,25 @@ typedef struct node{ struct node *next; }node; -typedef struct control{ - int value; - node *lhs; - node *rhs; -}control; +/// @short 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); -extern const control CONST_CONTR; +/// @short Free an entire B+ Tree +/// @param *root pointer to the root of the tree to free +void bp_destroy(node *root); -void bp_print(node *nd, int depth); -void bp_destroy(node *nd); +/// @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(); + +/// @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); -void bp_print_as_ll(node *nd); + +/// @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 +void bp_print_as_ll(node *root); #endif