Correction TP Arbres A
Transcription
Correction TP Arbres A
// POLYTECH MARSEILLE - INFO3 // Algorithmique, Programmation & Structures de données I // Année 2016-2017 // Les arbres : TP A // ================= #include #include #include #include <stdio.h> <stdlib.h> <malloc.h> <assert.h> // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // Types abstraits =============== // pour les arbres // --------------struct feuille { int type ; int val ; char etiq ; struct feuille *fg ; struct feuille *fd ; } ; // // // // // 1 = feuille, 0 = noeud valeur pour feuille étiquette pour noeud pointeur sur fils gauche pointeur sur fils droit typedef struct feuille t_feuille, * t_ptr_arbre, * tpf ; // pour les files // -------------typedef t_ptr_arbre data ; typedef struct maillon { data donnee ; struct maillon *suivant ; } maillon ; // Définit de type de donnée contenue dans un maillon typedef maillon * t_ptr_file ; // File = pointeur sur un maillon // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // Fonctions abstraites pour les arbres ==================================== // Création d'une feuille de valeur val // -----------------------------------t_ptr_arbre cree_feuille (int val) { tpf nouveau ; nouveau = (tpf)malloc (sizeof(feuille)) ; nouveau->type = 1 ; nouveau->val = val ; return nouveau ; } // Teste s'il s'agit d'une feuille ou d'un noeud // --------------------------------------------int est_feuille (t_ptr_arbre arbre) { return arbre->type ; } // Renvoie la valeur d'une feuille // ------------------------------int val_feuille (t_ptr_arbre arbre) { assert (est_feuille (arbre)) ; return arbre->val ; } // Création d'un noeud // ------------------t_ptr_arbre cree_noeud (char etiq, t_ptr_arbre fg, t_ptr_arbre fd) { tpf nouveau ; nouveau = (tpf)malloc (sizeof(feuille)) ; nouveau->type = 0 ; nouveau->etiq = etiq ; nouveau->fg = fg ; nouveau->fd = fd ; return nouveau ; } // Fils gauche t_ptr_arbre arbre_fg (t_ptr_arbre arbre) { assert (!est_feuille (arbre)) ; return arbre->fg ; } // Fils droit t_ptr_arbre arbre_fd (t_ptr_arbre arbre) { assert (!est_feuille (arbre)) ; return arbre->fd ; } // Etiquette d'un noeud char arbre_etiq (t_ptr_arbre arbre) { assert (!est_feuille (arbre)) ; return arbre->etiq ; } // Fonctions abstraites pour les files // ==================================== // Place un nouvel élément en queue de file // ---------------------------------------// // file[0] = pointeur de tête // file[1] = pointeur de queue void insere_file (data arbre, t_ptr_file file[]) { t_ptr_file nouveau ; nouveau = (t_ptr_file) malloc (sizeof(maillon)) ; nouveau->donnee = arbre ; nouveau->suivant = NULL ; // création d'un maillon if (file[0] == NULL) { file[0] = nouveau ; file[1] = nouveau ; } else { file[1]->suivant = nouveau ; file[1] = nouveau ; } // premier maillon d'une file vide } // Retire l'élément en tête de file et renvoie son contenu // ------------------------------------------------------data retire_file (t_ptr_file file[]) { data val ; t_ptr_file next ; assert (file[0] != NULL) ; val = file[0]->donnee ; next = file[0]->suivant ; free (file[0]) ; file[0] = next ; // nouveau maillon en queue de la file return val ; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // Parcours en profondeur ====================== // sous forme prefixe void profondeur_prefixe (t_ptr_arbre arbre, void action (t_ptr_arbre)) { if (arbre) { action (arbre) ; if (!est_feuille (arbre)) { profondeur_prefixe (arbre->fg, action) ; profondeur_prefixe (arbre->fd, action) ; } } return ; } // sous forme postfixe void profondeur_postfixe (t_ptr_arbre arbre, void action (t_ptr_arbre)) { if (arbre) { if (!est_feuille (arbre)) { profondeur_postfixe (arbre->fg, action) ; profondeur_postfixe (arbre->fd, action) ; } action (arbre) ; } return ; } // sous forme infixe void profondeur_infixe (t_ptr_arbre arbre, void action (t_ptr_arbre)) { if (arbre) { if (!est_feuille (arbre)) profondeur_postfixe (arbre->fg, action) ; action (arbre) ; if (!est_feuille (arbre)) profondeur_postfixe (arbre->fd, action) ; } return ; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // Parcours en largeur =================== void largeur (t_ptr_arbre arbre, void action (t_ptr_arbre)) { t_ptr_file file[2] ; t_ptr_arbre ptr ; if (arbre) { file[0] = NULL ; insere_file (arbre, file) ; while (file[0] != NULL) { ptr = retire_file (file) ; action (ptr) ; if (!est_feuille(ptr)) { if(ptr->fg) insere_file (ptr->fg, file) ; if (ptr->fd) insere_file (ptr->fd, file) ; } } } return ; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Autres exercices // ================ // Nombre de noeuds d'un arbre // --------------------------int nb_noeuds (t_ptr_arbre arbre) { if (arbre == NULL) return 0 ; if (est_feuille(arbre)) return 0 ; return 1+nb_noeuds(arbre->fg)+nb_noeuds(arbre->fd) ; } // Nombre de feuilles d'un arbre // ----------------------------int nb_feuilles (t_ptr_arbre arbre) { if (arbre == NULL) return 0 ; if (est_feuille(arbre)) return 1 ; return nb_feuilles(arbre->fg)+nb_feuilles(arbre->fd) ; } // Hauteur d'un arbre // -----------------int hauteur (t_ptr_arbre arbre) { int hg, hd ; if (arbre == NULL) return 0 ; if (est_feuille(arbre)) return 1 ; hg = hauteur(arbre->fg) ; hd = hauteur(arbre->fd) ; if (hg >= hd) return 1+hg ; return 1+hd ; } // Somme des feuilles d'un arbre // ----------------------------- int somme_feuilles (t_ptr_arbre arbre) { if (arbre == NULL) return 0 ; if (est_feuille(arbre)) return val_feuille (arbre) ; return somme_feuilles(arbre->fg)+somme_feuilles(arbre->fd) ; } // Copie miroir d'un arbre // ----------------------t_ptr_arbre miroir_arbre (t_ptr_arbre arbre) { if (arbre) { if (est_feuille(arbre)) return cree_feuille (val_feuille(arbre)) ; return cree_noeud (arbre_etiq(arbre), miroir_arbre(arbre_fd (arbre)), miroir_arbre(arbre_fg (arbre))) ; } return arbre ; } // Compte et imprime tous les sous-arbres // -------------------------------------int tous_sous_arbres (t_ptr_arbre arbre, void action (t_ptr_arbre)) { if (arbre) { profondeur_prefixe (arbre, action) ; printf ("\n") ; if (est_feuille (arbre)) return 1 ; return 1+tous_sous_arbres(arbre->fg, action)+tous_sous_arbres(arbre->fd, action) ; } return 0 ; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // Tests ===== // Impression simple des noeuds et des feuilles // -------------------------------------------- void traitement (t_ptr_arbre arbre) { if (est_feuille (arbre)) printf ("%d ", val_feuille(arbre)) ; else printf ("%c ", arbre_etiq(arbre)) ; } // Impression dans le format de l'énoncé d'un arbre // -----------------------------------------------void imprime_arbre_format_enonce (t_ptr_arbre arbre) { if (est_feuille (arbre)) printf ("%d", val_feuille (arbre)) ; else { printf ("(") ; imprime_arbre_format_enonce (arbre_fg(arbre)) ; printf ("%c", arbre_etiq(arbre)) ; imprime_arbre_format_enonce (arbre_fd(arbre)) ; printf (")") ; } return ; } // Enchainement des exercices pour un arbre // ---------------------------------------void test (t_ptr_arbre arbre) { int n ; printf ("\nprofondeur_prefixe : ") ; profondeur_prefixe (arbre, traitement) ; printf ("\nprofondeur_postfixe : ") ; profondeur_postfixe (arbre, traitement) ; printf ("\nprofondeur_infixe : ") ; profondeur_infixe (arbre, traitement) ; printf ("\nlargeur : ") ; largeur (arbre, traitement) ; printf ("\nnb_noeuds = %d", nb_noeuds(arbre)) ; printf ("\nnb_feuilles = %d", nb_feuilles(arbre)) ; printf ("\nhauteur = %d", hauteur(arbre)) ; printf ("\nsomme_feuilles = %d", somme_feuilles(arbre)) ; printf ("\n\nRecherche et comptage des sous-arbres\n") ; n = tous_sous_arbres (arbre, traitement) ; printf ("Nombre de sous-arbres = %d", n) ; return ; } int main (void) { tpf n1, n2 ; t_ptr_arbre arbre1, arbre2, arbre3, arbre4, arbre5, arbre6 ; // Création d'arbres arbre1 = cree_noeud( '+', cree_noeud( '*', cree_noeud( '+', cree_feuille( 1 ) , cree_feuille( 2 ) ) , cree_feuille( 3 ) ) , cree_noeud( '*', cree_feuille( 4 ) , cree_noeud( '*', cree_feuille( 5 ) , cree_feuille( 6 ) ) ) ) ; n1 = cree_noeud ('+', cree_feuille (1), cree_feuille (2)) ; n1 = cree_noeud ('+', n1, cree_feuille (3)) ; n1 = cree_noeud ('+', n1, cree_feuille (4)) ; n2 = cree_noeud ('*', cree_feuille (5), cree_feuille (6)) ; n2 = cree_noeud ('+', n2, cree_feuille (7)) ; arbre2 = cree_noeud ('+', n1, n2) ; arbre3 = cree_noeud( '-', cree_noeud( '*', cree_feuille( 5 ) , cree_noeud( '+', cree_feuille( 6 ) , cree_feuille( 9 ) ) ) , cree_noeud( '/', cree_noeud( '*', cree_feuille( 16 ), cree_feuille( 2 ) ) , cree_noeud( '/', cree_feuille( 4 ) , cree_feuille( 2 ) ) ) ) ; // Tests sur les arbres proposés printf ("Premier arbre :\n") ; imprime_arbre_format_enonce (arbre1) ; test (arbre1) ; arbre4 = miroir_arbre (arbre1) ; printf ("\n\nEtude de l'arbre miroir :\n") ; imprime_arbre_format_enonce (arbre4) ; test (arbre4) ; printf ("\n\nDeuxieme arbre :\n") ; imprime_arbre_format_enonce (arbre2) ; test (arbre2) ; arbre5 = miroir_arbre (arbre2) ; printf ("\n\nEtude de l'arbre miroir :\n") ; imprime_arbre_format_enonce (arbre5) ; test (arbre5) ; printf ("\n\nTroisieme arbre :\n") ; imprime_arbre_format_enonce (arbre3) ; test (arbre3) ; arbre6 = miroir_arbre (arbre3) ; printf ("\n\nEtude de l'arbre miroir :\n") ; imprime_arbre_format_enonce (arbre6) ; test (arbre6) ; return 0 ; }