#include #include #include #include #include "tree_primitives.h" #define PI 3.14159265 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)); /* Cette ligne peut faire débat : oper est un char *, * donc a priori peut être alloué par un malloc, * auquel cas il faudrait le free. * Cependant, si oper a été alloué autrement, * par exemple avec x.oper = "exemple", il ne faut * pas le free (et ça fera une segmentation fault si on tente de le free). * C ne permettant pas de tester si un char * a été malloc ou non, * pour éviter les cas d'erreurs, on ne met pas cette ligne. */ // free(value(a).oper); 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)) { // Appels récursifs sur le fils gauche, en augmentant le décalage graphical_print(left(a),depth+3); // affichage de la racine for(int i=0;i (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)); } } } /**************************************************** * Partie specifique aux expressions mathematiques *****************************************************/ void tree_print(tree_t a) { // ... } double evaluate(tree_t a, int val){ double res=0; // ... return res; } tree_t derivate(tree_t a){ s_base_t cnst={Constante,0,""}; tree_t res=cons(cnst,cons_empty(),cons_empty()); // ... return res; } tree_t build_tree(const char* exp, int debut, int* fin){ s_base_t cnst={Constante,0,""}; tree_t res=cons(cnst,cons_empty(),cons_empty()); // ... return res; }