From f99d2ae63f824dae55dfacbe16b09573c0519b89 Mon Sep 17 00:00:00 2001 From: vitawrap <thevitawrap@gmail.com> Date: Fri, 7 Apr 2023 16:33:04 +0200 Subject: [PATCH] =?UTF-8?q?Trees:=20=C3=A9quilibr=C3=A9s=20fonctionnels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test.c | 29 +++++++---- src/tree.c | 143 +++++++++++++++++------------------------------------ 2 files changed, 65 insertions(+), 107 deletions(-) diff --git a/src/test.c b/src/test.c index 01f78ec..82d411b 100644 --- a/src/test.c +++ b/src/test.c @@ -103,7 +103,7 @@ void test_multiple_list_insert_after() void viewStr(void* str) { - printf("%s", str); + printf("%s", (const char*)str); } int preceed(void* a, void* b) @@ -120,28 +120,37 @@ void test_trees_balanced() const char* b_str = "val de B!!"; int* c = malloc(sizeof(int)); *c = 94; const char* c_str = "val de C!!!"; + int* d = malloc(sizeof(int)); *d = 3; + const char* d_str = "val de D!!!"; - printf("Arbre 1: "); + printf("Arbre 1 : "); struct tree_t * tree = new_tree(0, preceed, viewInt, viewStr, freeInt, NULL); - tree_insert(tree, a, a_str); - tree_insert(tree, c, c_str); + tree_insert(tree, d, d_str); tree_insert(tree, b, b_str); + tree_insert(tree, c, c_str); + tree_insert(tree, a, a_str); view_tree(tree); + delete_tree(tree, 0, 0); - printf("Arbre 2: "); - tree = new_tree(0, preceed, viewInt, viewStr, freeInt, NULL); + printf("Arbre 1 (equilibré): "); + tree = new_tree(1, preceed, viewInt, viewStr, freeInt, NULL); + tree_insert(tree, d, d_str); tree_insert(tree, b, b_str); tree_insert(tree, c, c_str); tree_insert(tree, a, a_str); view_tree(tree); + delete_tree(tree, 0, 0); - printf("Arbre 3: "); - tree = new_tree(0, preceed, viewInt, viewStr, freeInt, NULL); - tree_insert(tree, b, b_str); + printf("Arbre 2 (equilibré): \n"); + tree = new_tree(1, preceed, viewInt, viewStr, freeInt, NULL); tree_insert(tree, a, a_str); + view_tree(tree); + tree_insert(tree, b, b_str); + view_tree(tree); tree_insert(tree, c, c_str); view_tree(tree); - + tree_insert(tree, d, d_str); + view_tree(tree); delete_tree(tree, 1, 0); } diff --git a/src/tree.c b/src/tree.c index 3543e62..5baa60d 100644 --- a/src/tree.c +++ b/src/tree.c @@ -228,6 +228,18 @@ void view_tree(const struct tree_t * T) { puts("]"); } +/** + * @brief + * Fonction utilitaire pour obtenir la taille d'un sous-arbre raçiné à \p node. +*/ +static int get_height(struct tree_node_t* node) { + if (node == NULL) + return 0; + int lh = get_height(get_left(node)); + int rh = get_height(get_right(node)); + return max(lh, rh) + 1; +} + /** * @brief * Effectuer une rotation gauche autour du nœud \p y. @@ -246,47 +258,16 @@ void view_tree(const struct tree_t * T) { static struct tree_node_t * rotate_left(struct tree_node_t * y) { assert(y); assert(get_right(y)); - // A FAIRE //ROTATION A GAUCHE struct tree_node_t *x = get_right(y); - struct tree_node_t *T2 = get_left(x); + struct tree_node_t *z = get_left(x); set_left(x, y); - set_right(y, T2); - - // MAJ DES BFACTOR - int bfactor_x = get_bfactor(x); - int bfactor_y = get_bfactor(y); - - if (bfactor_y == -2 && bfactor_x == -1) { - set_bfactor(x, 0); - set_bfactor(y, 1); - } else if (bfactor_y == -2 && bfactor_x == 0) { - set_bfactor(x, 0); - set_bfactor(y, 0); - } else if (bfactor_y == -1 && bfactor_x == 1) { - int bfactor_T2 = get_bfactor(T2); - if (bfactor_T2 == -1) { - set_bfactor(x, 0); - set_bfactor(y, 1); - } else if (bfactor_T2 == 0) { - set_bfactor(x, 0); - set_bfactor(y, 0); - } else if (bfactor_T2 == 1) { - set_bfactor(x, -1); - set_bfactor(y, 0); - } - } else if (bfactor_y == -1 && bfactor_x == -1) { - set_bfactor(x, 0); - set_bfactor(y, 0); - } else if (bfactor_y == -1 && bfactor_x == 0) { - set_bfactor(x, -1); - set_bfactor(y, 1); - } else if (bfactor_y == -2 && bfactor_x == -2) { - set_bfactor(x, 0); - set_bfactor(y, 0); - } + set_right(y, z); + + set_bfactor(y, max(get_height(get_left(y)), get_height(get_right(y))) + 1); + set_bfactor(x, max(get_height(get_left(x)), get_height(get_right(x))) + 1); return x; } @@ -309,42 +290,16 @@ static struct tree_node_t * rotate_left(struct tree_node_t * y) { static struct tree_node_t * rotate_right(struct tree_node_t * x) { assert(x); assert(get_left(x)); - // A FAIRE //ROTATION A DROITE struct tree_node_t *y = get_left(x); - struct tree_node_t *T2 = get_right(y); + struct tree_node_t *z = get_right(y); set_right(y, x); - set_left(x, T2); - - // MAJ DES BFACTORS - int bfactor_y = get_bfactor(y); - int bfactor_x = get_bfactor(x); - - if (bfactor_x == 1 && bfactor_y == 1) { - set_bfactor(x, 0); - set_bfactor(y, -1); - // if ((bfactor_x == 2 && bfactor_y == 1) || - // (bfactor_x == 1 && bfactor_y == 0) || - // (bfactor_x == 2 && bfactor_y == 2) || - // (bfactor_x == 2 && bfactor_y == 0)) - } else if (bfactor_x > 0 && bfactor_y >= 0) { - set_bfactor(x, 0); - set_bfactor(y, 0); - } else if (bfactor_x == 1 && bfactor_y == -1) { - int bfactor_T2 = get_bfactor(T2); - if (bfactor_T2 == -1) { - set_bfactor(x, 1); - set_bfactor(y, 0); - } else if (bfactor_T2 == 0) { - set_bfactor(x, 0); - set_bfactor(y, 0); - } else if (bfactor_T2 == 1) { - set_bfactor(x, 0); - set_bfactor(y, 1); - } - } + set_left(x, z); + + set_bfactor(x, max(get_height(get_left(x)), get_height(get_right(x))) + 1); + set_bfactor(y, max(get_height(get_left(y)), get_height(get_right(y))) + 1); return y; } @@ -385,10 +340,8 @@ static struct tree_node_t * insert_into_tree_node(struct tree_node_t * curr, voi else { // recherche récursif de la position à insérer + mise à jour du facteur d'équilibre int cmp = preceed(key, get_tree_node_key(curr)); if (cmp < 0) { //Cas 1 : clé du nv noeud inf a noeud curr => nv noeud dans curr->left - increase_bfactor(curr); curr->left = insert_into_tree_node(curr->left, key, data, balanced, preceed); } else if (cmp > 0) { //Cas 2 : clé du nv noeud sup a noeud curr => nv noeud dans curr->right - decrease_bfactor(curr); curr->right = insert_into_tree_node(curr->right, key, data, balanced, preceed); } }//FIN PARTIE 1 @@ -398,33 +351,33 @@ static struct tree_node_t * insert_into_tree_node(struct tree_node_t * curr, voi // Gérer ici les rotations // 6 cas int FEX = get_bfactor(curr); - int FEY = get_bfactor(FEX > 0? curr->left : curr->right); if(FEX == 2) { + int FEY = get_bfactor(get_left(curr)); if(FEY == 1 || FEY == 0) { - rotate_right(curr); + curr = rotate_right(curr); } else if(FEY == -1) { - rotate_left(FEX > 0? curr->left : curr->right); - rotate_right(curr); + curr->left = rotate_left(get_left(curr)); + curr = rotate_right(curr); } } - else if(FEY == -2) + else if(FEX == -2) { - if(FEX == -1 || FEX == 0) + int FEY = get_bfactor(get_right(curr)); + if(FEY == -1 || FEY == 0) { - rotate_left(FEX > 0? curr->left : curr->right); + curr = rotate_left(curr); } - else if(FEX == 1) + else if(FEY == 1) { - rotate_right(curr); - rotate_left(FEX > 0? curr->left : curr->right); + curr->right = rotate_right(get_right(curr)); + curr = rotate_left(curr); } } - } return curr; @@ -435,7 +388,7 @@ static struct tree_node_t * insert_into_tree_node(struct tree_node_t * curr, voi */ void tree_insert(struct tree_t * T, void * key, void * data) { struct tree_node_t* root = get_root(T); - struct tree_node_t* node = insert_into_tree_node(get_root(T), key, data, 0, T->preceed); + struct tree_node_t* node = insert_into_tree_node(get_root(T), key, data, tree_is_balanced(T), T->preceed); if (!root) set_root(T, node); increase_tree_size(T); @@ -531,11 +484,9 @@ static struct tree_node_t * remove_tree_node(struct tree_node_t * curr, void * k int cmp = preceed(key, get_tree_node_key(curr)); if (cmp < 0) { - decrease_bfactor(curr); curr->left = remove_tree_node(curr->left, key, data, balanced, preceed); } else if (cmp > 0) { - increase_bfactor(curr); curr->right = remove_tree_node(curr->right, key, data, balanced, preceed); } else { *data = get_tree_node_data(curr); @@ -548,37 +499,35 @@ static struct tree_node_t * remove_tree_node(struct tree_node_t * curr, void * k if (balanced && curr) { // PARTIE 2 : // Gérer ici les rotations - //6 cas - + // 6 cas int FEX = get_bfactor(curr); - int FEY = get_bfactor(FEX > 0? curr->left : curr->right); if(FEX == 2) { + int FEY = get_bfactor(get_left(curr)); if(FEY == 1 || FEY == 0) { - rotate_right(curr); + curr = rotate_right(curr); } else if(FEY == -1) { - rotate_left(FEX > 0? curr->left : curr->right); - rotate_right(curr); + curr->left = rotate_left(get_left(curr)); + curr = rotate_right(curr); } } - else if(FEY == -2) + else if(FEX == -2) { - if(FEX == -1 || FEX == 0) + int FEY = get_bfactor(get_right(curr)); + if(FEY == -1 || FEY == 0) { - rotate_left(FEX > 0? curr->left : curr->right); + curr = rotate_left(curr); } - else if(FEX == 1) + else if(FEY == 1) { - rotate_right(curr); - rotate_left(FEX > 0? curr->left : curr->right); + curr->right = rotate_right(get_right(curr)); + curr = rotate_left(curr); } } - - // A FAIRE } return curr; -- GitLab