1/51 Soutien Informatique Nicolas Castagné et François Portet PHELMA
2/51 Sommaire Allocation Mémoire Les types abstraits de données
3/51 Allocation dynamique de mémoire (stdlib.h,string.h) Réserver un espace mémoire pour une variable au moment de l exécution. Avantages : Différent de l allocation statique à la compilation. Dimensionnement : permet de créer des variables de grande dimensions quand celles ci sont inconnues au moment de l écriture du programme. Contrôle : permet un contrôle sur l utilisation mémoire. Utilisation uniquement quand on en a besoin (p.ex., grandes dimensions) Persistance : la mémoire n est libérée que sur ordre du programmeur ou à la fin du programme. Dangers : segfault : Erreur de segmentation Fuite mémoire : Toujours libérer la mémoire!!!
4/51 Fonctions de gestion dynamique de la mémoire Allocation void * calloc (size t nmemb, size t size); void * malloc (size t size); Redimensionnement void * realloc (void * ptr, size t size); Copier/initialiser void *memcpy(void *dest, const void *src, size t n); void *memset(void *s, int c, size t n); Libérer void free (void * ptr);
5/51 Exemple d allocation 1 main() 2 int i=0, dim=0; 3 double* t=null; 4 printf( Donner la dimension voulue ); 5 scanf( %d,&dim); 6 printf( t:%p et adresse t1%p n,t,&t); 7 8 t=calloc(dim, sizeof(*t)); /* on alloue APRES l obtention de la dimension*/ 9 10 printf( t:%p et adresse t1%p n,t,&t); 11 for (i=0; i dim; i++) 12 t[i]=2*i+1; 13 14 for (i=0; i dim; i++) 15 printf( %lf,t[i]); 16 17 free(t); /*on libere la memoire*/ 18
6/51 Organisation de la mémoire d un exécutable Le code est stocké dans une zone mémoire appelée.text Les variables globales sont gérées dans la zone.bss Allocation dans une zone mémoire gérée par l utilisateur : le tas (HEAP) Les variables locales sont gérées par le compilateur sur la pile (STACK) Organisation de la mémoire variable selon le processeur et le système d exploitation pile tas.bss.data.text système
7/51 Exemple d utilisation de la mémoire 1 int var global; 2 3 int carre(int para a) 4 int local d=0; 5 return para a*para a; 6 7 8 int somme carre(int para a,int para b) 9 int local c=0; 10 local c = carre(para a)+carre(para b); 11 return local c; 12 13 14 main() 15 int local a=1; 16 int *ptr = (int*)malloc(1*sizeof(*ptr)); 17 int *ptr2 = (int*)malloc(1*sizeof(*ptr2)); 18 int local b=2; 19 somme carre(local a,local b); 20 free(ptr); 21 free(ptr2); 22
8/51 Question 1 Faire une fonction qui prend en paramètres un tableau de double et sa dimension, et qui clone (crée un nouveau tableau et recopie) ce tableau. La fonction retourne le clone. 2 Faire le programme principal qui utilise cette fonction. Si le clone est modifié, le tableau initial est il modifié? 3 Quelle différence entre un tableau dynamique et un tableau automatique? 4 Pourquoi le programme suivant est il faux? 1 int * mauvais1 () int tab[10]; 2 for (i=0;i 10;i++) tab[i]=0; 3 return tab; 4 5 main() int * p; int i; 6 p=mauvais1(); 7 for (i=0;i 10;i++) printf( %d, p[i]); 8
9/51 Types abstraits de données? Un type abstrait est une structure de données pour laquelle on a défini les opérations essentielles. on ne se soucie : ni du type exact des données ni de l implémentation
9/51 Types abstraits de données? Un type abstrait est une structure de données pour laquelle on a défini les opérations essentielles. on ne se soucie : ni du type exact des données ni de l implémentation Il existe une séparation entre les types : Abstrait : qui ne s intéresse qu à la vision mathématique des opérations sur les données. Concret : qui est UNE implémentation particulière du type abstrait.
9/51 Types abstraits de données? Un type abstrait est une structure de données pour laquelle on a défini les opérations essentielles. on ne se soucie : ni du type exact des données ni de l implémentation Il existe une séparation entre les types : Abstrait : qui ne s intéresse qu à la vision mathématique des opérations sur les données. Concret : qui est UNE implémentation particulière du type abstrait. Exemples : pile, file, listes, arbres, graphes, dictionnaires, etc.
9/51 Types abstraits de données? Un type abstrait est une structure de données pour laquelle on a défini les opérations essentielles. on ne se soucie : ni du type exact des données ni de l implémentation Il existe une séparation entre les types : Abstrait : qui ne s intéresse qu à la vision mathématique des opérations sur les données. Concret : qui est UNE implémentation particulière du type abstrait. Avantages : pas à se soucier de l implémentation, hautement réutilisable, formalise les opérations, grand choix d implémentations concrètes.
10/51 Exemple type abstrait : le paquet Définition d un type paquet de T (T est un truc, cad un type quelconque) création : creer paquet : paquet T test : est vide : paquet T booleen ajouter un élément : entasse : paquet T T paquet T...
10/51 Exemple type abstrait : le paquet Définition d un type paquet de T (T est un truc, cad un type quelconque) création : creer paquet : paquet T test : est vide : paquet T booleen ajouter un élément : entasse : paquet T T paquet T... Implémentation : typedef int * paquet;
10/51 Exemple type abstrait : le paquet Définition d un type paquet de T (T est un truc, cad un type quelconque) création : creer paquet : paquet T test : est vide : paquet T booleen ajouter un élément : entasse : paquet T T paquet T... Implémentation : typedef int * paquet; int est vide(paquet p){if (p==null) return 0; else return 1;}
10/51 Exemple type abstrait : le paquet Définition d un type paquet de T (T est un truc, cad un type quelconque) création : creer paquet : paquet T test : est vide : paquet T booleen ajouter un élément : entasse : paquet T T paquet T... Implémentation : typedef int * paquet; int est vide(paquet p){if (p==null) return 0; else return 1;} int est vide(paquet p){return p==null;}
10/51 Exemple type abstrait : le paquet Définition d un type paquet de T (T est un truc, cad un type quelconque) création : creer paquet : paquet T test : est vide : paquet T booleen ajouter un élément : entasse : paquet T T paquet T... Implémentation : typedef int * paquet; int est vide(paquet p){if (p==null) return 0; else return 1;} int est vide(paquet p){return p==null;} int est vide(paquet p){return!p;}
1/51 La liste en informatique Une liste monomorphique est un ensemble fini mais variable d éléments rangés séquentiellement. Exemple : ( j,, aime, l,, informatique,. ) ( aimons, l,, informatique,. ) La liste est le support de la plupart des autres types abstraits (pile, file, arbres...) On la retrouve dans la quasi totalité des langages informatiques (notamment le LISP)
2/51 Définition abstraite de la liste Définition récursive d une liste L d éléments E (de type quelconque) : L = () L = E, L vide : L booleen ajoute : E L L tete : L E reste : L L Attention, il existe des langages qui permettent des listes polymorphiques (E peut être de plusieurs types différents). (12,3.14, informatique, (1,2,3), alloc)
13/51 Exemple d utilisation de liste chaînées en C On considère ici que E vaut int 1 /* liste1.c */ 2 main() 3 Liste l; 4 l=creerliste(); 5 l=ajout tete(9,l); 6 l=ajout tete(8,l); 7 l=ajout tete(1,l); 8 l=supprimer(8,l); 9 l=ajouter(5,l); 10 visualiser(l); 11
14/51 Représentation des listes chaînées en C Pour représenter une liste il faut : 1 un emplacement où stocker l élément 2 un moyen d accéder à l élément suivant
14/51 Représentation des listes chaînées en C Pour représenter une liste il faut : 1 un emplacement où stocker l élément 2 un moyen d accéder à l élément suivant Un élément = une variable d un type quelconque : double, int, structure, etc. Un maillon = une structure contenant un élément et une liste. Une liste = un pointeur vers un maillon ou vers null (liste vide).
5/51 Implémentation d un maillon 1 struct maillon 2 int val; 3 struct maillon * suiv; ; 4 typedef struct maillon Maillon; 5 typedef struct maillon * Liste;
5/51 Implémentation d un maillon 1 struct maillon 2 int val; 3 struct maillon * suiv; ; 4 typedef struct maillon Maillon; 5 typedef struct maillon * Liste; Besoin d une déclaration pour chaque type de variable?!?
5/51 Implémentation d un maillon 1 struct maillon 2 int val; 3 struct maillon * suiv; ; 4 typedef struct maillon Maillon; 5 typedef struct maillon * Liste; Besoin d une déclaration pour chaque type de variable?!? Définition d un maillon pseudo-paramétrable : typedef int ELEMENT; struct maillon { ELEMENT val; struct maillon * suiv;} ; typedef struct maillon Maillon; typedef struct maillon * Liste;
16/51 Création d une liste Création de liste : 1 Liste creer liste(void) 2 return NULL; /* la liste vide est representee par NULL */ 3 est vide : 1 int est vide(liste L) 2 return!l; /* la liste vide est representee par NULL */ 3 Exemple : 1 main() 2 Liste L = creer liste(); 3 if (est vide(l)) printf( la liste est vide n ); 4 else printf( la liste n est pas vide n ); 5
17/51 Liste : ajout en tête Ajouter 1 au début de la liste L contenant 9 1 Créer un nouveau maillon
17/51 Liste : ajout en tête Ajouter 1 au début de la liste L contenant 9 1 Créer un nouveau maillon 2 Mettre 1 dedans
7/51 Liste : ajout en tête Ajouter 1 au début de la liste L contenant 9 1 Créer un nouveau maillon 2 Mettre 1 dedans 3 Insérer ce nouveau maillon au bon endroit devant tous les autres, c est à dire
7/51 Liste : ajout en tête Ajouter 1 au début de la liste L contenant 9 1 Créer un nouveau maillon 2 Mettre 1 dedans 3 Insérer ce nouveau maillon au bon endroit devant tous les autres, c est à dire Indiquer à ce nouveau maillon que son suivant est celui qui contient 9
7/51 Liste : ajout en tête Ajouter 1 au début de la liste L contenant 9 1 Créer un nouveau maillon 2 Mettre 1 dedans 3 Insérer ce nouveau maillon au bon endroit devant tous les autres, c est à dire Indiquer à ce nouveau maillon que son suivant est celui qui contient 9 Indiquer que ce nouveau maillon est la tête de liste
7/51 Liste : ajout en tête Ajouter 1 au début de la liste L contenant 9 1 Créer un nouveau maillon 2 Mettre 1 dedans 3 Insérer ce nouveau maillon au bon endroit devant tous les autres, c est à dire Indiquer à ce nouveau maillon que son suivant est celui qui contient 9 Indiquer que ce nouveau maillon est la tête de liste ATTENTION à l ordre des deux dernières étapes
18/51 Ajout en tête : implémentation 1 Liste ajout tete(element e, Liste L) 2 Liste p=calloc(1,sizeof(*p)); 3 if (p==null) return NULL; 4 p- val=e; 5 p- suiv=l; 6 return p; 7
9/51 Liste : supprimer en tête Supprimer 1 au début de la liste L contenant 1 et 9 1 Récupérer le reste de la liste
9/51 Liste : supprimer en tête Supprimer 1 au début de la liste L contenant 1 et 9 1 Récupérer le reste de la liste 2 Libérer la mémoire de 1
9/51 Liste : supprimer en tête Supprimer 1 au début de la liste L contenant 1 et 9 1 Récupérer le reste de la liste 2 Libérer la mémoire de 1 3 Retourner le reste de la liste
9/51 Liste : supprimer en tête Supprimer 1 au début de la liste L contenant 1 et 9 1 Récupérer le reste de la liste 2 Libérer la mémoire de 1 3 Retourner le reste de la liste ATTENTION à l ordre des deux premières étapes
20/51 Suppression en tête : implémentation 1 Liste supp tete(liste L) 2 Liste p = creer liste(); 3 if (!est vide(l)) 4 p=l- suiv; 5 free(l); 6 7 return p; 8
21/51 Parcours itératif d une liste 1 void visualiser(liste L) 2 Liste p=creer liste(); 3 for (p=l;!est vide(p); p=p- suiv) 4 affiche(&p- val); 5
2/51 Autres listes Liste doublement chaînée : permettent le retour en arrière ajout d un pointeur sur le précédent Liste circulaire : permet le parcours permanent de la liste la fin de la liste pointe sur le début de la liste (au lieu de NULL)
23/51 Exercices liste 1 Faire une fonction qui recherche si un élément (un réel) est présent dans une liste : cette fonction retourne l adresse du maillon de la liste contenant la valeur si elle est présente ou NULL sinon 2 Faire une fonction qui fusionne deux listes 3 Faire une fonction qui insère en tête dans une liste doublement chaînée 4 Faire une fonction qui insère en queue dans une liste doublement chaînée 5 Faire une fonction qui insère en tête dans une liste circulaire simplement chaînée 6 Faire une fonction qui ajoute un réel dans une liste triée et doublement chaînée de réels. 7 Faire une fonction qui prend une liste en paramètre, et créée une nouvelle liste contenant les éléments en ordre inverse. A t on besoin de connaître la nature des éléments de la liste?
24/51 Exercice - sur machine Objectif : définir les fonctions de base sur les listes de cartes que nous réutiliserons par la suite. Travail à réaliser : 1 Soit les fichiers : carte.h, liste.h et test liste. Écrivez les fichiers liste.c et carte.c 2 Tester votre programme à l aide de test liste.c et du Makefile.
25/51 Récursivité Définition : objet informatique autoréférent
25/51 Récursivité Définition : objet informatique autoréférent Exemple : n! = n (n 1)! factorielle(n) = n factorielle(n 1)
25/51 Récursivité Définition : objet informatique autoréférent Exemple : n! = n (n 1)! factorielle(n) = n factorielle(n 1) int fac(int n) { return(n * fac(n-1)); }
25/51 Récursivité Définition : objet informatique autoréférent Exemple : n! = n (n 1)! factorielle(n) = n factorielle(n 1) int fac(int n) { return(n * fac(n-1)); } Pourquoi n est-ce pas correct?
26/51 Programmation récursive 1 Réduire le problème initial à un problème de taille inférieure 2 Trouver la formule de récurrence (le cas général) 3 Préciser le cas connu
26/51 Programmation récursive 1 Réduire le problème initial à un problème de taille inférieure 2 Trouver la formule de récurrence (le cas général) 3 Préciser le cas connu 1 Taille du problème : Paramètre n décroissant 2 Décomposition du cas général fac(n)=n*fac(n-1) 3 Cas particulier et arrêt fac(0) = 1
27/51 La factorielle recursive 1 int fac(int n) 2 if(n==0) return 1; 3 return (n * fac(n-1)); 4
28/51 Récursivité : conclusion Simplicité de programmation : rapide à écrire facile à comprendre
28/51 Récursivité : conclusion Simplicité de programmation : rapide à écrire facile à comprendre Coût : mémoire : pile (passage des paramètres, création variables locales) CPU : appel de fonctions et sauvegarde de contexte
28/51 Récursivité : conclusion Simplicité de programmation : rapide à écrire facile à comprendre Coût : mémoire : pile (passage des paramètres, création variables locales) CPU : appel de fonctions et sauvegarde de contexte À utiliser à bon escient à éviter pour les problèmes non recursif
29/51 Exercices récursivité avec liste chaînée 1 Écrire la fonction visualiser de manière récursive. 2 Écrire la fonction ajouter en queue de manière récursive. 3 Écrire une fonction ajouter en ordre croissant de manière récursive.
0/51 Copie de surface ou profonde? Copie profonde : Dans p- val=e, e est supposé être copié dans le maillon pointé par p. Mais si e : contient un pointeur alors nécessité de recopier l ensemble des données pointées dans un nouvel espace mémoire. besoin d une fonction copie pour ELEMENT copie en cascade si plusieurs pointeurs imbriqués explosion mémoire si e est très gros (p.ex., vidéos, base de données...)
0/51 Copie de surface ou profonde? Copie de surface : Dans p- val=e, le type ELEMENT est un pointeur. La copie ne fait que sauvegarder l adresse de l élément défini à l extérieur de la fonction ajoute. Avantages : pas de recopie intempestive de mémoire. possibilité d être extrêmement générique : on garde les mêmes fonctions quel que soit le type on peut choisir de mixer des types Désavantages : pas de contrôle sur les modifications extérieures (p.ex., liste triée). pas de contrôle sur la modification de l élément en mémoire (p.ex., free ou realloc).
31/51 Implémentation d une shallow liste Une modification! ELEMENT devient juste un void *. 1 struct maillon 2 void* val; 3 struct maillon * suiv; ; 4 typedef struct maillon Maillon; 5 typedef struct maillon * Liste;
32/51 Liste shallow : modification des opérations de base 1 Liste ajout tete(void* e, Liste L) 2 Liste p=calloc(1,sizeof(*p)); 3 if (p==null) return NULL; 4 p- val=e; 5 p- suiv=l; 6 return p; 7 1 void* supp tete(liste* L) 2 void * p=null; 3 if (!est vide(*l)) 4 Liste m=l- suiv; 5 p = L- val; 6 free(*l); 7 *L=m; 8 9 return p; 10
33/51 Liste shallow : nécessité du cast (coercition) 1 main() 2 Liste entiers = strings = creer liste(), p; 3 entiers = rempli entier(entiers); 4 strings = rempli blabla(strings); 5 6 for (p=entiers,!est vide(p),p=p- suiv) 7 printf( entier = %d n, *(int *)p- val); 8 9 for (p=strings,!est vide(p),p=p- suiv) 10 puts((char *)p- val); 11 12 supprime liste entier(entiers); 13 supprime liste blabla(strings); 14
33/51 Liste shallow : nécessité du cast (coercition) 1 main() 2 Liste entiers = strings = creer liste(), p; 3 entiers = rempli entier(entiers); 4 strings = rempli blabla(strings); 5 6 for (p=entiers,!est vide(p),p=p- suiv) 7 printf( entier = %d n, *(int *)p- val); 8 9 for (p=strings,!est vide(p),p=p- suiv) 10 puts((char *)p- val); 11 12 supprime liste entier(entiers); 13 supprime liste blabla(strings); 14 Que se passerait-il si : strings = rempli entier(entiers); printf( entier = %d\n, p- val);
34/51 Liste shallow : ajout d éléments 1 Liste rempli entier(liste l) 2 int i=0, *p; 3 4 for (int i;i 10;i++) 5 p = malloc(sizeof(*p)); 6 *p=i; 7 l= ajout tete((void*) p, l); 8 9 return l; 10
34/51 Liste shallow : ajout d éléments 1 Liste rempli entier(liste l) 2 int i=0, *p; 3 4 for (int i;i 10;i++) 5 p = malloc(sizeof(*p)); 6 *p=i; 7 l= ajout tete((void*) p, l); 8 9 return l; 10 Que se passerait-il si : p = &i si p = malloc(...) était en dehors de la boucle for.
35/51 Liste shallow : suppression d éléments 1 supprime liste blabla(liste l) 2 Liste p = l; char* string=null; 3 4 for(p=l,!est vide(p);p=p- suiv) 5 string = (char *) supp tete(l); 6 free(string); 7 8
35/51 Liste shallow : suppression d éléments 1 supprime liste blabla(liste l) 2 Liste p = l; char* string=null; 3 4 for(p=l,!est vide(p);p=p- suiv) 5 string = (char *) supp tete(l); 6 free(string); 7 8 Que se passerait-il si : pas de free(string);, une des chaînes de caractères a déjà été libérée.
6/51 Liste shallow vs. liste deep Liste profonde : + copie réelle des éléments + pas d effets de bord - utilisation intempestive de la mémoire - difficile à utiliser avec plusieurs listes de types différents Liste de surface : + extrêmement générique (une seule définition suffit pour tout le programme) + utilisation raisonnable de la mémoire - effets de bord possibles - nécessité constante de coercition (cad cast) En conclusion la liste shallow est très pratique mais... très dangereuse...
37/51 Exercices liste 1 Faire une fonction qui recherche si un élément est présent dans une liste : cette fonction retourne l adresse du maillon de la liste contenant la valeur si elle est présente ou NULL sinon. Cette fonction doit être générique et prend une fonction de comparaison compar en entrée. 2 Écrire cette fonction de comparaison pour une structure CARTE et une structure PERSONNE. 3 Utiliser cette fonction de comparaison pour écrire une fonction de liste triée générique.
38/51 Les piles Analogie : pile d assiettes Seul le sommet de la pile est accessible 2 opérations : empiler ou dépiler Propriété Le dernier arrivé est le premier traité! LIFO : Last In First Out
39/51 Pile : exemple 1 main() 2 Pile p; 3 ELEMENT e; 4 p=creer pile(); 5 p=empiler(10,p); 6 p=empiler(20,p); 7 p=empiler(30,p); 8 e= depiler(&p); 9 printf( Depiler : valeur de l element depile %lf n,e); 10 visualiser(p); 11
40/51 Pile : Opérations La pile est une liste pour laquelle on autorise uniquement 4 opérations de modification. 1 Pile empiler(element,pile); 2 Pile supprimer(pile); 3 ELEMENT sommet(pile); 4 ELEMENT depiler(pile*);
40/51 Pile : Opérations La pile est une liste pour laquelle on autorise uniquement 4 opérations de modification. 1 Pile empiler(element,pile); 2 Pile supprimer(pile); 3 ELEMENT sommet(pile); 4 ELEMENT depiler(pile*); Attention : certaines de ces opérations ne sont pas applicables avec une pile vide
40/51 Pile : Opérations La pile est une liste pour laquelle on autorise uniquement 4 opérations de modification. 1 Pile empiler(element,pile); 2 Pile supprimer(pile); 3 ELEMENT sommet(pile); 4 ELEMENT depiler(pile*); Attention : certaines de ces opérations ne sont pas applicables avec une pile vide Attention à depiler. Cette fonction doit réaliser 2 actions : 1 retourner l élément au sommet de pile, et 2 modifier le sommet de pile (qui doit contenir un élément de moins).
41/51 Pile : Exercices 1 Écrire les fonctions empiler, depiler. 2 Comment écrit on les fonctions empiler, depiler en utilisant les fonctions ajout tete et supp tete des listes chaînées.
42/51 Exercice - sur machine Objectif : définir les fonctions de base sur les piles de cartes que nous réutiliserons par la suite. Travail à réaliser : 1 Soit les fichiers : carte.h, liste.h, pile.h et test pile.c. Écrivez le fichier pile.c. 2 Tester votre programme à l aide de test pile.c et du Makefile.
43/51 Les files Analogie : file d attente La tête ET la fin de la file sont accessible 2 opérations : enfiler et défiler Propriété Le premier arrivé est le premier traité! FIFO : First In First Out
44/51 File : exemple 1 main() 2 Pile p; 3 ELEMENT e; 4 p=creer file(); 5 p=enfiler(10,p); 6 p=enfiler(20,p); 7 p=enfiler(30,p); 8 e= defiler(&p); 9 printf( Defiler : valeur de l element defile %lf n,e); 10 visualiser(p); 11
45/51 File : Opérations La file est une liste pour laquelle on autorise uniquement 4 opérations de modification. 1 Pile emfiler(element,pile); 2 Pile supprimer(pile); 3 ELEMENT tete(pile); 4 ELEMENT defiler(pile*);
45/51 File : Opérations La file est une liste pour laquelle on autorise uniquement 4 opérations de modification. 1 Pile emfiler(element,pile); 2 Pile supprimer(pile); 3 ELEMENT tete(pile); 4 ELEMENT defiler(pile*); Attention : certaines de ces opérations ne sont pas applicables avec une file vide
45/51 File : Opérations La file est une liste pour laquelle on autorise uniquement 4 opérations de modification. 1 Pile emfiler(element,pile); 2 Pile supprimer(pile); 3 ELEMENT tete(pile); 4 ELEMENT defiler(pile*); Attention : certaines de ces opérations ne sont pas applicables avec une file vide Attention à defiler. Cette fonction doit réaliser 2 actions : 1 retourner l élément en tête de file, et 2 modifier la file (qui doit contenir un élément de moins).
46/51 File : Représentation en liste chaînée On doit pouvoir accéder rapidement à la tête ET la fin de la file. 1 typedef struct maillon 2 ELEMENT val; 3 struct maillon * suiv; Maillon; 4 5 typedef struct 6 Maillon *tete; 7 Maillon *fin; File;
46/51 File : Représentation en liste chaînée On doit pouvoir accéder rapidement à la tête ET la fin de la file. 1 typedef struct maillon 2 ELEMENT val; 3 struct maillon * suiv; Maillon; 4 5 typedef struct 6 Maillon *tete; 7 Maillon *fin; File; On ne peut pas réutiliser directement les fonctions de gestion des listes
46/51 File : Représentation en liste chaînée On doit pouvoir accéder rapidement à la tête ET la fin de la file. 1 typedef struct maillon 2 ELEMENT val; 3 struct maillon * suiv; Maillon; 4 5 typedef struct 6 Maillon *tete; 7 Maillon *fin; File; On ne peut pas réutiliser directement les fonctions de gestion des listes Il faut maintenir deux informations ce qui complique la gestion de la file
47/51 File : Représentation en liste chaînée circulaire La file est définie par un seul pointeur sur la FIN avec une Liste CIRCULAIRE. À la fin de la liste, on ajoute un lien qui ramène au début de la liste. La tête est définie par l élément qui suit la fin : tete = liste- suiv. La fin est définie par la liste : fin= liste. 1 2 typedef struct maillon 3 ELEMENT val; 4 struct maillon * suiv; Maillon; 5 6 typedef Maillon * File;
48/51 File : Enfiler 1 File enfiler(element e, File f) 2 File c = calloc(1,sizeof(*c)); 3 c- val = e; 4 if (est vide(f)) 5 c- suiv = c; 6 7 else 8 c- suiv = f- suiv; 9 f- suiv=c; 10 11 return c; 12 13 14 main() 15 File l= creer file(); 16 /* Enfiler 8 sur une file vide */ 17 l=enfiler(8,l); 18 l=enfiler(9,l); 19 l=enfiler(1,l); 20
49/51 Files : Exercices 1 Files par listes chaînées circulaires : écrire la fonction defiler 2 Files par listes chaînées circulaires : écrire la fonction visualiser file
50/51 Exercice - sur machine Objectif : définir les fonctions de base sur les files de cartes que nous réutiliserons par la suite. Travail à réaliser : 1 Soit les fichiers : carte.h, liste.h, file.h et test file.c. Écrivez le fichier file.c. 2 Testez votre programme à l aide de test file.c et du Makefile.
Références I 51/51