c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
6) Allocation Dynamique de Mémoire &
Listes Chaînées IUT GTR Sophia-Antipolis Sophia-Antipolis
[email protected] OctOct-De Decc 2000 2000
c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
Plan 1] Introduction 2] Les Fonctions d'Allocation Dynamique de Mémoire 3] Les Listes Chaînées 3.1] Insertion en Tête 3.2] Insertion en Queue 3.3] Insertion en Ordre
c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
1] Introduction Possible d’allouer de la mémoire à l'exécution (normalement la mémoire est allouée statiquement à la compilation).
Intérêts : – Gestion Optimale de la mémoire • Réserv Réservati ation on d'une d'une tail taille le préci précise se de mémo mémoire ire qd qd on en a besoi besoin n • Libé Libéra rati tion on de la mémo mémoir iree qd on ne s’en s’en sert sert plus plus
– Possibilité de définir des listes d’éléments de taille variable (≠ des tableaux qui sont de taille fixe)
Problème : Les Pointeurs !!!
2] Les Fonctions d'Allocation 1/3 c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
Bibliothèque
Allocation de Mémoire void * malloc(size_t malloc(size_t size); Fonction retournant un pointeur sur un espace mémoire réservé à un élément de taille size ou bien NULL si l’allocation est impossible. La mémoire allouée n’est pas initialisée. Réservation de Mémoire pour une chaîne :
char * nom = (char *) malloc(sizeof malloc(sizeof (char)*(strlen (char)*(strlen(tabMaChaine) (tabMaChaine) + 1); 1); /* longueur de la chaîne contenue dans le tableau tabMaChaine, plus un pour le caractère de fin de chaîne, multipliée par la taille en mémoire d’un caractère */ Réservation de Mémoire pour un Elève :
Eleve * pE pEleve = (Eleve *) malloc(sizeof malloc(sizeof (Eleve)); (Eleve));
2] Les Fonctions d'Allocation 2/3 c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
Bibliothèque Allocation de Mémoire (suite) void * calloc(size_t calloc(size_t nbElem, size_t tailleElem); Fonction retournant un pointeur sur un espace mémoire réservé à un tableau de nbElem éléments (chaque élément ayant tailleElem comme taille) ou bien NULL si l’allocation est impossible. La mémoire allouée est initialisée avec des zéros.
void * realloc(void realloc(void * p, size_t newTaille); Change en newTaille la taille de l'élément pointé par p (le contenu est conservé). Retourne un pointeur sur le nouvel espace alloué ou bien NULL si la réallocat réallocation ion est imposs impossible ible (dans ce cas *p n’est pas modifié).
2] Les Fonctions d'Allocation 3/3 c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
Bibliothèque Libération de Mémoire void free( free(void * p); Libère l’espace mémoire pointé par p; elle ne fait rien si p vaut NULL. p doit être un pointeur sur un espace mémoire alloué par malloc, calloc ou realloc. Il est conseillé de déallouer la mémoire dont on ne se sert plus.
free(nom); free(pEleve);
3] Listes Chaînées 1/2 c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
tete
Simple Chaînage
Chaînage d'éléments Chaque élément possède l'Adresse de son Suivant (pointeur) Structure de données de Tail Taille le Vari Variab able le Insertions/Suppressions d'éléments se font par des Modifications de Chaînage (≠ des décalages en mémoire contiguë comme dans les tableaux) Le Dernier Elément de la liste pointe sur une valeur nil est représe représenté nté par par la constant constantee particulière appelée appelée nil (en C, nil NULL de la bibliothèque ) noté graphiquement tete
Double Chaînage
queue
c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
3] Listes Chaînées 2/2 Définition du Type des Eléments typed typedef ef stru struct ct _Ele _Eleve ve { char * nom; int id;
Structure nommée pour permettre la définition récursive du champ suiv
struct _Eleve *suiv; } Eleve;
Définition d'un Elément de la Liste Eleve * p = (Eleve (Eleve *)malloc(si *)malloc(sizeof zeof(Elev (Eleve)); e)); p 1 p->id = 1; p p->s p->sui uiv v = NULL NULL;;
p
1
p 1
p->nom = (char*)malloc(sizeof(c (char*)malloc(sizeof(char)*(strlen(chain har)*(strlen(chaine) e) +1); strcpy(p->nom, chaine);
Il faut maintenant l'Insérer dans la Liste
p
"Tournesol" 1
c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
3.1] Insertion en Tête 1/2 tete
tete
Liste LIFO (Las (Lastt In, In, Firs Firstt Out Out)) "Tournesol" 1
tete
"Haddock" 2
tete
1
"Tintin" 3
"Tournesol"
"Haddock" 2
1
"Tournesol"
3.1] Insertion en Tête 2/2 c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
Elément à insérer
Etat de la liste chaînée tete
"Haddock" 2
"Tournesol"
"Tintin"
p
3
1
1] Fait pointer le champ suiv de l'élément à insérer sur l'élément pointé par tête i.e. p->suiv = tete;
"Tintin"
p tete
3
"Haddock" 2
2] Fait pointer tete sur l'élément à insérer i.e. tete = p;
p
1
"Tintin" 3
tete
"Tournesol"
"Haddock" 2
1
"Tournesol"
c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
3.2] Insertion en Queue 1/2 tete
tete
Liste FIFO (First In, First Out) "Tournesol" 1
tete
"Tournesol" 1
tete
"Haddock"
2
"Tournesol" "Haddock" 1
2
3
"Tintin"
3.2] Insertion en Queue 2/2 ptr if (tet (tete e == NULL) NULL) /* cas cas par parti ticu culie lierr si la têt tête e est est nil nil */ "Tournesol" "Haddock" tete tete = p; else { 1 2 /* 1] Recher Recherche che le dernie dernier r élément de la liste */ ptr = tete; ptr while (ptr->suiv != NULL) NULL) tete ptr = ptr->suiv; "Tournesol" "Haddock" /* 2] Fait pointer pointer le le champ champ suiv du dernier élément sur l'élément à 1 2 insérer */ ptr->suiv = p; "Tintin" }
c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
3
p
3.3] Insertion en Ordre 1/2 c / s i b r u o C . e n i r a C / l e n n o s r e p / s i s a o / r f . a i r n i . p o s w w w / / : p t t h
(ici ordre alphabétique) tete
tete
"Tournesol" 1
tete
"Haddock" 2
tete
1
"Haddock" 2
"Tournesol"
3
"Tintin" 1
"Tournesol"
3.3] Insertion en Ordre 2/2
if (tet (tete e == NULL) NULL) ptr /* cas cas part partic icul ulie ierr si la têt tête e est est nil nil */ c / tete = p; "Haddock" "Tournesol" s i b r { /*Recherche où insérer selon l'ordre*/tete uelse o C . 2 1 if (strcmp(tete->nom, p->nom) >0){ e n i r a /* insertion en tête */ C / l e p->s p>sui uiv v = te tete te;; te tete te = p; n "Haddock" ptr n o s } else { r e "Tournesol" tete p / /* 1] Recherche le précédent */ s i s a ptr = tete->suiv; 2 o 1 / r f . while while ((ptr((ptr->su >suiv iv != NULL NULL)) && p a 3 i r n i (strcmp(ptr->suiv->nom, (strcmp(ptr->suiv->nom, p->nom)<0)) "Tintin" . p o s ptr ptr = ptrptr->s >sui uiv; v; w ptr w "Haddock" /* 2] Fait pointer suiv de l'élément à insérer sur w / / : élément pointé par le précédent */ p tete "Tournesol" t t h p->suiv = ptr->suiv; 2 1 /* 3] Chaîne le suivant du précédent avec l'élément à insérer */ insérer */ p 3 ptr->suiv = p; "Tintin"