Première partie 1 Séries des exercices Page 1
Série1 : Les pointeurs Exercice1: Analyser le programme suivant: void main() int a[10], *pa, x; a[0] = 11; a[1] =22; a[2] = 33; a[3] = 44; pa = &a[0]; x = *pa; pa++; x = *pa; x = *pa + 1; x = *(pa + 1); x = *++pa; x = ++*pa; x = *pa++; Exercice2: Interpréter les instructions suivantes: char *pc; int *pi,*pj,*pk; float *pr; pc = (char*)malloc(10); pi = (int*)malloc(16); pr = (float*)malloc(24); pj = (int*)malloc(sizeof(int)); Page 2
pk = (int*)malloc(3*sizeof(int)); free(pi); free(pr); Exercice 3: adr1 et adr2 sont des pointeurs pointant sur des réels. Le contenu de adr1 vaut -45,78; le contenu de adr2 vaut 678,89. Ecrire un programme qui affiche les valeurs de adr1, adr2 et leur contenu. Exercice 4: Saisir un texte. Ranger les caractères en mémoire. Lire le contenu de la mémoire et y compter le nombre d'espaces et de lettres e. Exercice 5 : Écrire une fonction int* concat_tab(int t1[], int n1, int t2[], int n2) qui prend en paramètres deux tableaux et leurs tailles respectives, et qui renvoie leur concaténation. Il faudra allouer un nouveau tableau pour contenir cette concaténation. Exercice 6 : Écrire une fonction char* concat_string(char* s1, char* s2) qui prend en arguments deux chaînes de caractères et qui renvoie leur concaténation (il faut allouer un nouveau tableau pour la contenir). Exercice 7 : On se donne une structure «livre» : typedef struct livre Livre; char titre[20]; int cote; int prix; On veut créer une bibliothèque de plusieurs livres, sous la forme d un tableau de livres. 1) Écrire une fonction init qui renvoie un tableau de n livres, qui alloue la mémoire nécessaire et qui initialise les champs à 0 ou à la chaîne de caractères vide. 2) Écrire une fonction qui permet la saisie d un livre. 2) Écrire une fonction qui affiche un tableau de n livres. 4) Écrire une fonction qui fait l échange des livres d indice i et j dans le tableau de livres. Page 3
Série 2: La récursivité Exercice 1 : Écrire une fonction récursive qui permet de calculer la factorielle d'un entier positif. Exercice 2 : Écrire une fonction récursive qui permet de calculer la somme des n (n 0) premiers termes (à partir de 1 jusqu à n). Exercice 3 : Écrire une fonction récursive qui permet de calculer les nombres de "Fibonacci" qui sont définis par : Fibonacci (0) = 0, Fibonacci (1) = 1, et pour tout n > 1, Fibonacci (n) = Fibonacci (n-1) + Fibonacci (n-2) Exercice 4 : Écrire une fonction récursive qui permet de calculer le plus grand diviseur commun de deux entiers naturels strictement positifs. Exercice 5 : Écrire une fonction récursive qui permet de calculer la valeur de la fonction d Ackermann définie de la manière suivante pour m 0 et n 0 : Acker(m, n) = Acker(m-1, Acker(m, n-1)) Acker(0, n) = n+1 pour n > 0 Acker(m, 0) = Acker(m-1, 1) pour m > 0 Page 4
Exercice 6 : Il s agit de calculer la somme des entiers allant de 0 à un entier donné N et qui ont la même parité que N. Par exemple, Pour la valeur 6, la fonction doit rendre la valeur 12. (6+4+2+0 = 12) Pour la valeur 5, la fonction doit rendre la valeur 9. (5+3+1 = 9) a) Écrire une fonction itérative permettant de résoudre ce problème. b) Résoudre le même problème par une fonction récursive. Exercice 7 : Ecrire une fonction récursive qui teste si un nombre positif n est un multiple de 5. Exercice 8 On souhaite écrire une fonction calculant la division par 2 d'un entier sans utiliser l'opérateur / mais seulement les opérateurs + et -. Pour cela on remarque la propriété suivante : Ecrire cette fonction d une manière récursive. Exercice 9 On souhaite écrire une fonction calculant le produit de deux entiers m et n sans utiliser l'opérateur * mais seulement les opérateurs + et -. Pour cela on remarque la propriété suivante : Ecrire cette fonction d une manière récursive. Page 5
Exercice 10 Ecrire une fonction récursive qui retourne Cnp, le nombre de combinaisons de p éléments d'un ensemble comportant n éléments. Une définition récursive de Cnp est donnée par : pour les cas de base et par : pour le cas de récurrence : Cn p = Cn-1 p-1 + Cn-1 p Exercice 11 : Écrire une fonction récursive qui permet de dire si un mot donné est un palindrome ou pas. Exercice 12 : Écrire une fonction récursive qui retourne la valeur numérique d une sous chaîne de taille nbr d une chaîne de caractères composée de chiffres. (Exemple : a = valeurnumerique("5123",3) a =512) Exercice 13 : Écrire une fonction récursive qui compte le nombre d occurrences d un entier dans un tableau d entiers. Exercice 14 : Écrire une fonction récursive qui permet d inverser un tableau d entiers Page 6
Série 3: Les Listes Exercice 1 : Ecrire le code de fichier ELTDBL.H qui permet de déclarer le type double comme structure de données adoptée. a) Ecrire le code de fichier ELSDD.H qui permet de choisir le type double comme structure de données. b) Ecrire le code de fichier ELTDBL.C qui permet de définir les primitives pour une réalisation par des doubles de TDA ELEMENT. c) Ecrire une fonction qui renvoie la position de la première occurrence d un élément dans une liste de doubles. Cette fonction renvoie 0 si l élément est inexistant. d) Ecrire une fonction qui renvoie la moyenne de valeurs d une liste de doubles. e) Ecrire une fonction qui permet de trier une liste de doubles en ordre croissant. Exercice 2 : a) Ecrire le code de fichier ELTSTR.H qui permet de déclarer le type string (chaine de caractères) comme structure de données adoptée. b) Ecrire le code de fichier ELSDD.H qui permet de choisir le type string comme structure de données. c) Ecrire le code de fichier ELTSTR.C qui permet de définir les primitives pour une réalisation par des strings de TDA ELEMENT. d) Ecrire un programme qui lit des chaînes de caractères sur l'entrée standard. A la rencontre de la chaîne "la", il affichera la liste des chaînes déjà saisies. A la rencontre de la chaîne "li", il affichera cette liste dans l'ordre inverse. Exercice 3 : Écriture d'un programme interactif de gestion des étudiants. Ce programme affichera le menu suivant : 1 Ajout d un étudiant. 2 Recherche d un étudiant. 3 Suppression d un étudiant. 4 Tri de liste des étudiants. 5 Affichage de liste des étudiants. Page 7
6 Vider la liste. 7 Quitter. En outre, ce programme effectuera le traitement correspondant au choix effectué. Les étudiants seront sauvegardés dans une liste (sauvegarde indirect). Un étudiant est représenté par la structure suivante : typedef struct char nom[50] ; /* nom et prénom d un étudiant */ char adr[80] ; /* adresse d un étudiant */ int insc ; /* numéro d inscription */ ETUDIANT ; a) Ecrire le code de fichier ELTETD.H qui permet de déclarer le type ETUDIANT comme structure de donnée adoptée. b) Ecrire le code de fichier ELSDD.H qui permet de choisir le type ETUDIANT comme structure de donnée. c) Ecrire le code de fichier ELTETD.C qui permet de définir les primitives pour une réalisation par des ETUDIANTS de TDA ELEMENT. d) Ajouter les fonctions nécessaires et écrire le programme principal correspondant. Exercice 4 : a) Ecrire une fonction qui permet de vérifier l existence d un élément dans une liste non triée (recherche séquentiel). b) Ecrire une fonction qui permet de purger une liste (supprimer les doublons). c) Ecrire une fonction qui permet de trier une liste en ordre décroissant. d) Ecrire une fonction qui permet de rechercher un élément dans une liste triée en ordre croissant (recherche dichotomique). e) Ecrire une fonction qui permet d inverser une liste. f) Ecrire une fonction qui permet de concaténer deux listes (sans doublons). g) Ecrire une fonction qui permet de renvoyer l intersection de deux listes. h) Ecrire une fonction qui permet de fusionner deux listes triées en ordre croissant. La liste résultante doit être triée. Page 8
Série 4 : Les listes chainées Exercice 1 : On suppose qu on dispose des fichiers ELTDBL.H et ELTDBL.C implémentés dans l exercice 1 de la série 3. Dans cet exercice, on s intéresse à traiter une liste simplement chaînée de réels. 1) Ecrire une fonction MinMax qui permet de calculer le min et le max dans une liste chaînée de réels. 2) Ecrire une fonction MoyProd qui permet de calculer la moyenne et le produit d une liste chaînée de réels. 3) Ecrire une fonction qui permet d inverser une liste de réels. 4) Ecrire une fonction qui permet de fusionner deux chaînes de réels à une position donnée. Exercice 2 : Un livre est caractérisé par : 1) son numéro (entier) 2) son titre (chaîne de caractère) 3) son auteur (chaîne de caractère) 4) son éditeur (chaîne de caractère) 5) son prix (réel) 1) Ecrire le fichier ELTLVR.H qui définit un livre comme étant une implémentation du TDA ELEMENT, sachant qu on veut stocker les livres indirectement. 2) Ecrire le fichier ELTLVR.C 3) Ecrire une fonction qui permet de retourner le nombre d exemplaires d un livre donné. 4) Ecrire une fonction qui permet de calculer le nombre de livres d un éditeur donné. 5) Ecrire une fonction qui permet de retourner un tableau de livre d un auteur donné. 6) Ecrire une fonction qui retourne le livre le plus cher. 7) Ecrire une fonction qui permet de calculer la valeur de la bibliothèque (somme des prix des livres). Page 9
8) Ecrire une fonction qui permet de retourner une partie de la liste de livres à partir d une position Deb à une position Fin. Exercice 3 : Un abonné est caractérisé par : - son numéro - son nom - sa ville 1) Ecrire le fichier ELTABN.H qui définit un abonné comme étant une implémentation du TDA ELEMENT, sachant qu on veut stocker les abonnés indirectement. 2) Ecrire le fichier ELTABN.C 3) Ecrire une fonction qui permet de vérifier s il existe dans la liste un abonné dont le nom est N et la ville est V. 4) Ecrire une fonction qui permet de calculer le nombre d abonnés d une ville donnée. 5) Ecrire une fonction qui permet de retourner un tableau des villes distinctes des abonnés. 6) Ecrire une fonction qui retourne un tableau d abonné d une ville donnée. Page 10
Série5: Les expressions arithmétiques (pile et file) Exercice1: 1) Exécuter manuellement l évaluation ds expressions postfixées suivantes : a) 6 5 2 3 + 8 * + 3 + * b) 6 3 2-1 + / 9 6 - * 2) Exécuter manuellement la transformation de cette expression infixée a+b*c+(d*e+f)*g en expression postfixée. Exercice 2: On veut écrire un programme permettant d évaluer un expression postfixée utilisant comme opérateurs uniquement les opérateurs binaires +, -, * et / et manipulant uniquement des chiffres (les nombres sont des chiffres 0, 1, 2,.9), autrement dit un entier est un seul chiffre. On suppose que l expression est donnée sans qu il y ait des séparateurs (pas d espaces entre les opérateurs et les valeurs). Par exemple : 36*25+- (qui est l équivalent en infixée (3*6) (2+5)) Ecrire le programme correspondant à l évaluation de ce type d expression postfixée Exercice 3: En reprenant les même hypothèses que l exercice précédent, écrire le programme correspondant à l évaluation d une expression préfixée (exemple -*36+25) Exercice 4: Page 11
On veut généraliser l évaluation des expressions arithmétiques postfixées (par rapport à l exercice 2). - Les opérateurs utilisées sont les opérateurs binaires +, -, * et / - Les entiers manipulés peuvent être composées de plus qu un chiffre (ex : 345, 89, etc). - Il est impératif qu il y ait un espace (séparateur) entre deux entiers ou deux opérateurs ou un entier et un opérateur. Par exemple : 3 6* 2 5 + - (qui est l équivalent en infixée de (3*6) (2 + 5)) 99 65 + 567 7 + * (qui est l équivalent en infixée de (99 + 65) * (567 + 7)) Ecrire le programme correspondant à l évaluation de ce type d expression postfixée. Exercice 5: En se basant sur les hypothèses de l exercice précédent, écrire un programme permettant d transformer une expression infixée en une expression infixée Rappelons qu il faut qu il y ait toujours un séparateur (espace) entre les entiers, les opérateurs et aussi les parenthèses ( et ). Page 12
Série 6 : Les Arbres Exercice 1 a) Ecrire une fonction ARBIN creerarbreentiers() qui permet de créer et de renvoyer l arbre d entiers suivant : b) Ecrire une fonction int feuilles(arbin a) qui permet de compter le nombre de feuilles d un arbre. c) Ecrire une fonction void inverserarbre(arbin a) qui permet d inverser un arbre d entiers (fils gauche devient fils droit et vice versa). Exercice 2 Procédure FileArbre (A : ArbreBinaire) F : File de noeuds d un arbre binaire P : Noeud d un arbre binaire Début Initialiser(F) // Création d une file vide Enfiler(F, A->refRacine) Tantque NonVide(F) Faire P<-Défiler(F) Afficher(P->Info) Si P->FG!= NULL Alors Enfiler(F, P->FG) Finsi Si P->FD!= NULL Alors Enfiler(F, P->FD) Finsi Fin Tantque Fin En utilisant la procédure FileArbre, donner l'ordre d'affichage des noeuds de l'arbre ci-dessous Page 13
. Exercice 3 Dans cet exercice, on se propose de traiter des arbres binaires partiellement équilibrés en utilisant le type arbre binaire ARBIN. Un arbre binaire est dit partiellement équilibré s il est vide ou si pour chaque noeud de l arbre les hauteurs de ses sous arbres gauches et droits diffèrent de au plus 1. a) En utilisant les primitives d un arbre binaire (ARBIN), écrire une fonctions récursive int equilibre(arbin a) qui retourne 1 (vrai) si l arbre a satisfait la définition d un arbre binaire partiellement équilibré et 0 (faux) sinon. Soit un arbre binaire a manipulant des éléments nommés CarHauteur. Un élément CarHauteur est déclaré dans le fichier ELTCARHAUT.H comme suit : typedef struct char car ; int hauteur ; CarHauteur, * ELEMENT ; b) Ecrire une fonctions récursive void calculerhauteurs(arbin a) qui prend en argument un arbre binaire de ce type. Cette fonction modifie l arbre en entrée en mettant à jour le champ hauteur de chaque noeud de façon à ce qu il contienne la hauteur du sous arbre dont il est la racine. Page 14
c) En employant la fonction calculerhauteurs, donner une nouvelle implémentation de fonction equilbre (question a) Exercice 4 Soit le type arbre épine dorsale qui est un arbre ternaire structuré de la manière suivante : a) Remplir les blancs relatifs à la figure ci-dessus : - La profondeur de cet arbre est.. - L ordre de cet arbre est.. - Le résultat du parcours postfixé est.. - La liste A,B,Z,X,C,E,Y,D,R,M,F,N est un le résultat du parcours.. - Les noeuds B, Z, X appartiennent au niveau.. - A-Z-E-R est.. L implémentation chaînée de la structure de données épine dorsale va se faire dans les fichiers ARBED.H et ARBED.C. b) Ecrire le code de fichier ARBED.H qui permet de déclarer le type arbre épine dorsale. c) Ecrire une fonction itérative int tailleed(arbed a) qui permet de renvoyer la taille d un arbre épine dorsale. d) Ecrire une fonction itérative int verifiered(arbed a) qui permet de renvoyer 1 (vrai) si l arbre a est épine dorsale et 0 si non (faux). Exercice 5 On définit un tas comme étant un arbre binaire parfait tel que l information contenue dans chaque noeud est inférieure à celles contenues dans ses deux fils. Le minimum de l ensemble représenté par un tas est donc à la racine (C est le cas de l exemple ci-dessous). Les traitements sur les tas nécessitent que chaque noeud puisse accéder à son père ainsi qu à ses fils. Page 15
On se propose d implémenter les primitives de structure de données TAS suivants : - int tasinserer(tas t, ELEMENT e) ; - ELEMENT supprimermin(tas t) ; - ELEMENT tasracine(tas t) ; - int tasvide(tas t) ; - int tassature(tas t) ; - etc a) Ecrire le code de fichier TASPTR.H qui permet d implémenter le tas d une façon chaînée. Un arbre binaire parfait de taille n peut se représenter de façon très compacte dans un tableau T de taille au moins égale à n + 1 (la première cellule de T, de rang 0, n est pas utilisée). La représentation est la suivante: La racine est en T[1] et si un noeud est en T[i], son fils gauche est en T[2i] et son fils droit en T[2i+1]. b) Donner la représentation dans le cas de l arbre ci-dessus. c) Quel est l instruction qui permet de récupérer le père d un noeud i. d) Pourquoi cette représentation contiguë est-elle adéquate avec les Tas. e) Ecrire le code de fichier TASTAB.H qui permet d implémenter le tas d une façon contiguë. Insertion d un élément à un tas Le problème est d ajouter un élément e à un tas tout en conservant une structure de tas. On commence par Page 16
rajouter l élément e comme feuille au dernier niveau de l arbre puis on échange l information du nœud portant e avec celui de son père jusqu à ce que, pour respecter la structure de tas, e ne soit pas inférieur à l information du père du noeud qui le porte. Par exemple, pour rajouter 4 au tas donné dans l exemple ci-dessus, on obtient les étapes suivantes : f) Ecrire une fonction itérative int tasinserer(tas t, ELEMENT e) qui permet d insérer un élément e à un tas t. En supposant que la fonction NOEUDTAS dernierpere(tas t) qui retourne le père de e est donnée. Dans l exemple précédant la fonction dernierpere() retourne le noeud contenant 8. La complexité temporelle de cette fonction est de O(N), N étant la taille de l arbre. g) Donner la complexité temporelle de cet algorithme avec une brève explication. Suppression du minimum d un tas (la racine) h) Ecrire une fonction itérative ELEMENT supprimermin(tas t) qui permet de supprimer le minimum du tas courant et retournant la valeur de ce minimum, en utilisant la représentation contiguë. L idée est de supprimer la dernière feuille du dernier niveau après avoir recopié son information à la racine, puis, pour respecter la structure de tas, de faire redescendre cette valeur en la comparant au contenu de ses fils, par un processus inverse de celui de l insertion. La figure suivante illustre ce processus dans le cas de l exemple. Page 17
Exercice 6 (Session Principale 2007/2008) Un arbre lexicographique est un arbre binaire qui représente un dictionnaire tel que: - Chaque noeud contient un caractère - Le fils droit signifie le caractère suivant dans le mot. - Le fils gauche signifie le caractère suivant dans le dictionnaire (alternative). Le caractère * signifie la fin d un mot. Il est à noter qu'un noeud "fin de mot" n'a pas de sousarbre droit mais peut avoir un sous arbre gauche. Par exemple, l'arbre suivant correspond aux 8 mots : a bac balle ballon bas base bus sac Page 18
La structure arbre lexicographique peut être implémentée par un arbre binaire dont les éléments sont de caractères (ELTCAR.H et ELTCAR.C). a) Donner la trace d exécution de la fonction f suivante : public void f (ARBIN a) char mot[20] ; g (a->refracine, mot,0); void g (NOEUD n, char m[], int i) if (n!= NULL) if (n->info == * ) m[i] = \0 ; printf( %s, m); else m[i] = n->info; g (n->fd, m, i + 1); g (n->fg, m, i); Page 19
Quelle est l utilité de cette fonction? b) Ecrire une fonction récursive int existerec(arbin a, char mot[]) qui permet de tester l existence d un mot dans un arbre lexicographique. c) Ecrire une fonction itérative int existeit(arbin a, char mot[]) qui permet de tester l existence d un mot dans un arbre lexicographique. Page 20
Deuxième partie 2 Devoirs surveillés Page 21
Devoir surveillé n 1 (2009-2010) On propose d écrire un programme permettant de représenter les polynômes. Un polynôme est un ensemble de monômes. Un monôme est composé de deux entiers : coefficient puissance L interface de ce type est la suivante (fichier POLYPRIM.H) POLYNOME PolynomeCreer() ; int PolynomeTaille(POLYNOME) ; int estvide(polynome) ; int estsaturee(polynome) ; POLYNOME SaisiePolynome(int) ; Void Reduction(POLYNOME) ; On se propose d implémenter quelques primitives de cette interface sous la forme d une liste chaînée de monômes (fichiers POLYPTR.H pour les déclarations des structures et POLYPTR.C pour le code). La figure ci-contre est une représentation du polynôme : 1) Ecrire le fichier POLYPTR.H qui définit les structures nécessaires. (3 points) typedef struct structnoeud int coefficient; int puissance ; struct structnoeud * suivant; structnoeud, * NOEUD; typedef struct NOEUD tete; int lg; Page 22
lastruct,*polynome; Sinon ils peuvent utiliser le type ELEMENT qui correspond à une structure contenant les deux int. 2) En se limitant aux fonctionnalités de l interface POLYPRIM.H implémenter la fonction POLYNOME SaisiePolynome(int n) qui permet de saisir un polynôme de n monômes. (5 points) POLYNOME SaisiePolynome(int n) NOEUD p,q; POLYNOME L=PolynomeCreer(); if(l==null) return L ; if(n>=1) p=noeudcreer(); scanf(`` %i ``, &p->puissance) ; scanf(`` %i ``, &p->coefficient) ; L->tete=p; p->suivant=null; L->lg++; for(int i=1;i<n;i++) q=noeudcreer(); scanf(`` %i ``, &q->puissance) ; scanf(`` %i ``, &q->coefficient) ; p->suivant=q; p=q; L->lg++; p->suivant=null; return L; Page 23
3) En se limitant aux fonctionnalités de l interface POLYPRIM.H implémenter la fonction void Reduction(POLYNOME P) qui permet de réduire la taille du polynôme P en effectuant la somme des monômes ayant la même puissance. (6 points) En appliquant cette fonction à l exemple précédent, on obtiendra void Reduction(POLYNOME P) NOEUD p=l->tete,q,s; int i=1; while (p!=null) s=p; q=p->suivant; while(q!=null) if((q->puissance == (p->puissance) p->coefficient+=q-> coefficient; s->suivant=q->suivant; noeuddetruire(q) ; L->lg--; q=s->suivant ; else q=q->suivant; Page 24
s=s->suivant; p=p->suivant; 4) Donner la complexité de chaque fonction implémentée et argumenter votre réponse. (4 points) Complexité fonction : POLYNOME SaisiePolynome (int n) O(n) Complexité fonction : Void Reduction( POLYNOME P) n+(n-1)+(n-2)+ +1= (n²-n)/2 ==O(n²) 5)Quels sont les modifications nécessaires pour avoir une liste chainée circulaire de monômes. (2 points) Si quelqu un a compris l idée que pour une liste circulaire chainée la queue doit pointer sur la tête, il peut avoir les 2 pts du barème. Page 25
Devoir surveillé n 2 (2010-2011) Exercice 1: Définition d un type de donnée MATRICE (12 points) On veut définir un nouveau type abstrait : MATRICE sans avoir recours au TDA LISTE On suppose qu on dispose des fichiers ELTINT.H et ELTINT.C implémentés qui permettent de réaliser le TDA ELEMENT par un entier et du fichier MATPRIM.H qui définit les primitives du TDA MATRICE. Les opérations de base sont : la création d une matrice, l ajout et la suppression d une ligne ou d une colonne et l accès à un élément de la matrice. MATRICE CreeMatrice(); Int InsererLigne(MATRICE,int) Int InsererColonne(MATRICE,int) Int SupprimerLigne(MATRICE,int) Int SupprimerColonne(MATRICE,int) Element Récuperer(MATRICE, Int, int) 1. Ecrire le fichier MATPTR.H qui définit une matrice simplement chainée comme étant une implémentation du TDA MATRICE (Il vous faudra également définir NOEUD) (3 points) Page 26
#ifndef _MATPTR_H #define _MATPTR_H #include "ELTPRIM.h" typedef struct structnoeud ELEMENT info; struct structnoeud * suivant_ligne; struct structnoeud * suivant_colonne; structnoeud, * NOEUD; typedef struct NOEUD tete; int NL; int NC; lastruct,*matrice; #endif 2)Ecrire une fonction int Supprimer (MATRICE M, int k) qui permet de supprimer la k ième ligne de la matrice. Cette fonction retourne 1 si l opération de suppression a été effectuée avec sucées, 0 sinon. (9 points) supprimer (MATRICE M, int k ) int i, succee=1; NOEUD p, q,n; if (estvide(m)) else printf ("\nmatrice vide"); succee=0; if ((k < 1) (k> M->NL)) printf ("\nposition invalide"); succee=0; Page 27
else q = M->tete; if (k == 1) /*suppression de la première ligne*/ M->tete=M->tete->suivant_ligne; for(i=1;i<=l->nc; i++) p=q; q=q->suivant_colonne; noeuddetruire(p); else /*cas général (k > 1) */ for (i=1; i<k; i++) p = q; q = q->suivant_ligne; for(i=1;i<=l->nc; i++) p->suivant_ligne=q->suivant_ligne; p=p->suivant_colonne ; n=q ; q=q->suivant_colonne ; noeuddetruire(n); (L->NL)--; return succee; Page 28
Exercice 2 : expression bien parenthésée (8 points) En utilisant la structure pile contigüe, Ecrire une fonction qui vérifie si une expression est bien parenthésée. Nous considérerons des expressions arithmétiques, formées de nombres entiers et des quatre opérateurs. Ces expressions pourront être parenthésée à l aide de deux types de parenthèses différentes : () et []. Une expression est dite bien parenthésée si pour toute parenthèse fermante d un certain type, il existe une parenthèse ouvrante du même type qui la précède, et qui n a pas encore été fermée. NB : vous pouvez utiliser les primitives de piles. Exemple : Les expressions suivantes sont bien parenthésées : ([3 + 5] (2 9)) 1 + 4 ([(2)]) Les expressions suivantes ne sont pas bien parenthésées : (3 + 5] : les types de parenthèses ne correspondent pas. ((3) : une des deux parenthèses n a pas été fermée. (4)) : on ferme une parenthèse qui n a pas été ouverte. int VerifPar(char* ch ) int i = 1, n=strlen(ch); int res; Pile P = PileCreer(); for (i=0; i <n; i++) if (ch[i] == ( ch[i] == [ ) Empiler(P, ch[i]) ; else if (ch[i]= = ) ) if (EstVide(P) Sommet(P) == [ ) res=0; ; else Depiler(P) ; else if (ch[i]= = ] ) if (EstVide(P) sommet(p) == ( ) res= 0 ; else Depiler(P) ; if (EstVide(P) ) res= 1 ; else res= 0 ; PileDetruire(P); Page 29
Return res; Page 30
Devoir surveillé n 3 (2012-2013) On se propose de définir la structure Dictionnaire permettant d avoir une liste de mots avec leurs définitions. Pour cela on procédera comme suit : La structure Mot est défini par : Une chaîne (chaîne de caractères), ses explications (tableau de chaîne de caractères), et le nombre d explications de cette chaîne. La structure Dictionnaire est définie par une liste doublement chaînée de définitions. 1. Ecrire le code du fichier ELTMOT.H qui permet de réaliser le TDA ELEMENT pour une structure MOT (en stockage indirect). 2. Ecrire le code du fichier ELTMOT.C qui permet de définir les primitives de TDA ELEMENT. 3. Ecrire une fonction InsererDef qui permet d'ajouter une explication pour un mot donné dans le dictionnaire s il existe. 4. Ecrire une procédure DefinitionMOT qui donne le nombre et les explications d une chaîne donnée. Corrigé du devoir surveillé n 3 (2012-2013) 1. 2 pts #ifndef _ELTMOT_H #define _ELTMOT_H 2. 8 pts typedef struct char chaine [100]; char explications [100][100]; int nbre; mot, *ELEMENT; #endif #include "ELTPRIM.h" 1 ELEMENT elementcreer(void) ELEMENT e; e=(element)malloc(sizeof(mot)); return e; Page 31
0,5 void elementdetruire (ELEMENT e) free (e); 2 void elementlire(element * e) int i; printf("donner un mot:\n"); scanf("%s",&(*e)->chaine); do printf("donner le nombre d'explications de ce mot:\n"); scanf("%d", &(*e)->nbre); while((*e)->nbre<=0); for(i=0; i<(*e)->nbre; i++) printf("donner l'explication N %d:",i+1); scanf("%s", &((*e)->explications[i])); printf("\n"); 1,5 void elementafficher(element e) int i; printf("le mot est: %s\n", e->chaine); printf("les definitions donnees pour ce mot sont:\n"); for(i=0; i<e->nbre; i++) printf("explication N %d: %s \n", i+1, e->explications[i]); 0,5 void elementaffecter(element * e1, ELEMENT e2) *e1=e2; 2 void elementcopier(element * e1, ELEMENT e2) int i; strcpy((*e1)->chaine, e2->chaine); (*e1)->nbre=e2->nbre; for(i=0; i<(*e1)->nbre; i++) strcpy((*e1)->explications[i], e2->explications[i]); 0,5 int elementcomparer(element e1, ELEMENT e2) Page 32
return strcmp(e1->chaine,e1->chaine); 3. 5 pts #include "LSTPRIM.h" int InsererDef(LISTE l, ELEMENT e, char expli []) int taille, trouve=0; NOEUD p=l->tete; if (estvide(l)) printf("liste vide\n"); return 0; else while(!trouve && p!=null) if (elementcomparer(p->info, e) == 0) taille=p->info->nbre; strcpy(p->info->explications[taille],expli); p->info->nbre++; trouve=1; else p=p->suivant; return trouve; 4. 5 pts void DefinitionMOT(LISTE l, char chaine[], char res[100][100], int * nb) int i; NOEUD p=l->tete; int trouve=0; if (estvide(l)) printf("liste vide\n"); else while(!trouve && p!=null) if (strcmp(p->info->chaine, chaine) == 0) for(i=0; i<p->info->nbre; i++) Page 33
trouve=1; strcpy(res[i], p->info->explications[i]); *(nb)=p->info->nbre; else p=p->suivant; Page 34
Troisième partie 3 Sujets Des Examens Page 35
Examen corrigé N 1 (2009/2010) Exercice 1 (12 points) : Un arbre d expressions est un arbre binaire où les noeuds sont ou bien des opérateurs ou bien des opérandes: 1) En supposant qu on dispose d un arbre d expressions non vide, écrire la fonction ABRFile(ARBIN a, int O, FILE F) qui permet de parcourir un arbre a de telle sorte à créer l expression arithmétique qui lui correspond sous forme d une FILE F. La nature de l expression demandée est précisé par l entier O (O=1: expression préfixée, O=2: expression infixée, O=3: expression postfixée). Comme le montre l exemple suivant: Remarque : Vous pouvez utiliser toutes les fonctionnalités du TDA File, par contre pour les arbres seule la structure peut être utilisée (toute autre fonctionnalité doit être programmée). void ABRFile(ARBIN a, int O, FILE F) AjouterNoeud (a->refracine, F, O); =================================== void AjouterNoeud(NOEUD n, FILE F, int O) Page 36
if(n) switch(o) case 1: /* parcours préfixé */ Enfiler (F, n->info) ; AjouterNoeud (n->fg, F, O); AjouterNoeud (n->fd, F, O); break; case 2: /* parcours infixé */ AjouterNoeud (n->fg, F, O); Enfiler (F, n->info) ; AjouterNoeud (n->fd, F, O); break; case 3: /* parcours postfixé */ AjouterNoeud (n->fg, F, O); AjouterNoeud (n->fd, F, O); Enfiler (F, n->info) ; break; default: printf("erreur d'affichage: ordre %d incorrect.\n", ordre); 2) Afin d évaluer l expression arithmétique obtenue dans F, quelle est la (ou les meilleurs) valeur de O qu il faut choisir. Justifier votre réponse Les expressions préfixées et postfixées ont l avantage que l ordre de priorité est déterminé par leur position dans ces expressions. Les expressions préfixées et postfixées peuvent être facilement évaluées en utilisant les piles. Page 37
3) Supposons que O=1, donner les différentes étapes qui permettent d évaluer F= * + 5 6 - -4 9 en utilisant une pile P (à chaque étape préciser le contenu de P et celui de F) Exercice 2 (8 points): Page 38
Soit P = (a1,..., an) une pile non vide de n éléments (avec a1 le sommet de la pile). On désire modifier le contenu de la pile P pour qu'elle contienne (a2,..., an, a1) (c'est-à-dire le sommet a1 est déplacé au fond de la même pile). Cette opération s appelle la rotation d une pile. On considèrera l'implémentation chainée suivante de la pile typedef struct structnoeud ELEMENT info; struct structnoeud * suivant; structnoeud, * NOEUD; typedef struct NOEUD tete; /* Sommet de la pile */ lastruct,*pile; 1) Donner une implémentation en langage C de la fonction Rotation (Pile P), sans utiliser les primitives du TDA Pile. void Rotation(Pile P) NOEUD n, m; If (P->tete!= null) && (P->tete->suivant!= null) n = P->tete; P->tete = P->tete->suivant; m = P->tete; while m->suivant!=null m = m->suivant m->suivant = n; n->suivant = null; 2) Donner la complexité temporelle et spatiale d'un algorithme qui appelle la fonction rotation m fois sur une pile qui contient n éléments Complexite temporelle O(nm) spatiale O(n) Page 39
Références http://www.montefiore.ulg.ac.be/~geurts/cours/sda/2011/01-intro.pdf R. Malgouyres, F. Feschet, Z. Zrour. Algorithmique et structures de données en C 2011. Page 40