#include #include #include "tree_primitives.h" tree_t cons_empty() { /* Pas besoin d'allouer de la mémoire inutilement et de créer un nœud. * Retourner NULL suffit. */ return NULL; } tree_t cons(s_base_t v, tree_t fg, tree_t fd) { /* On alloue uniquement la mémoire pour le nœud que l'on crée. v, fg et fd * ont déjà été créés, la mémoire a donc déjà été allouée.*/ tree_t a = (tree_t) malloc(sizeof(s_node_t)); /* affectations */ a->val = v ; a->fg = fg; a->fd = fd ; return a ; } int is_empty(tree_t a) { /* Dans le cas où la restitution de l'arbre vide serait implémentée * différemment, le test de vacuité serait différent : il faudrait tester les * pointeurs de a */ return a == NULL; } s_base_t value(tree_t a) { return a->val; } tree_t left(tree_t a) { return a->fg ; } tree_t right(tree_t a) { return a->fd; } void change_value(tree_t pa, s_base_t new_value) { pa->val = new_value; } void change_left(tree_t pa, tree_t new_left) { pa->fg = new_left; } void change_right(tree_t pa, tree_t new_right) { pa->fd = new_right; } void free_tree(tree_t a) { /* test indispensable pour traiter le cas de l'arbre vide à libérer */ if(!is_empty(a)) { /* On libére d'abord récursivement la mémoire sur les fils gauche et * droit, puis sur le nœud lui-même. */ free_tree(left(a)); free_tree(right(a)); free(a); } } /* Parcours préfixe : donnée préfixe(fils_gauche) préfixe(fils_droit) */ void prefix(tree_t a) { /* Test pour traiter le cas de l'arbre vide */ if (!is_empty(a)) { /* Affichage de la donnée de l'arbre */ print(value(a)); // Appels récursifs sur les fils gauche et droit prefix(left(a)); prefix(right(a)); } } /* On passe la profondeur en paramètre pour obtenir une indentation cohérente */ void graphical_print(tree_t a, int depth) { if (!is_empty(a)) { // affichage de la racine for(int i=0;i 0 et changement de direction (dans la filiation) il faut afficher le lien if(i>0 && trace[i] != trace[i-1]){ printf("|"); }else{ printf(" "); } // completer avec des espaces printf(" "); } printf("+--"); print(value(a)); printf("\n"); // Appels récursifs sur le fils gauche, en augmentant le décalage, en précisant qu'on va à droite trace[depth]=1; graphical_print_link(right(a), depth+1, trace); } } int size(tree_t a) { int size_a=0; if (!is_empty(a)) { /* La taille d'un arbre correspond à la somme des tailles de ses fils + 1 * (le nœud courrant. If faut donc faire deux appels récursifs. */ size_a = 1 + size(left(a)) + size(right(a)); } //Dans le cas de l'arbre vide, la taille vaut 0 (initialisation de size_a en //début de fonction) return size_a; } int height(tree_t a) { int height_a=0; if (!is_empty(a)) { /* La hauteur d'un arbre correspond à 1 + le max des hauteurs de ses fils. * Il faut donc deux appels récursifs. * Comme il faut accéder deux fois à la hauteur d'un fils, on stocke les * hauteurs dans des variables pour plus d'efficacité. */ int hfg=height(left(a)); int hfd=height(right(a)); height_a = 1+((hfg) > (hfd) ? hfg : hfd); } return height_a; } /* On peut aussi implémenter cette fonction en utilisant un _Bool. Mais on * tâche d'être cohérent si on a commencé à implémenter compare() sans _Bool * mais avec des int. */ int exists(tree_t a, s_base_t v) { if (is_empty(a)) { return 0; } else { if (compare(value(a),v)==0) { return 1; } else { /* Appels récursifs : si on n'a pas trouvé v, il faut tester sa présence * dans les fils gauche et droit */ return (exists(left(a),v) || exists(right(a),v)); } } } /* Non demandé dans le sujet. */ int is_degenerated(tree_t a) { int deg=1; if (!is_empty(a)) { if (is_empty(left(a))) { if (is_empty(right(a))) { deg=1; } else { deg=is_degenerated(right(a)); } } else { if (! is_empty(right(a))) { deg=0; } else { deg=is_degenerated(a->fg); } } } return deg; }