IFT-2000: Structures de Données Listes chaînées Dominic Genest, 2009.

Slides:



Advertisements
Présentations similaires
Bratec Martin ..
Advertisements

NOTIFICATION ÉLECTRONIQUE
Fragilité : une notion fragile ?
SEMINAIRE DU 10 AVRIL 2010 programmation du futur Hôtel de Ville
Phono-sémantique différentielle des monosyllabes italiens
MAGGIO 1967 BOLOGNA - CERVIA ANOMALIES DU SOMMEIL CHEZ L'HOMME
droit + pub = ? vincent gautrais professeur agrégé – avocat
Transcription de la présentation:

IFT-2000: Structures de Données Listes chaînées Dominic Genest, 2009

Les désavantages des tableaux dynamiques Les éléments risquent dêtre déplacés dans un tout nouvel espace-mémoire à chaque ajout ou suppression. Ce qui fait que les itérateurs (pointeurs) à ces éléments nont aucune garantie de demeurer valides à partir du moment où on ajoute ou supprime. Insérer dans un tableau à une position quelconque (ni au début ni à la fin) implique un décalage dune partie des éléments, ce qui peut être coûteux. Les éléments doivent être placés de façon contigüe (dans un seul gros bloc) en mémoire, ce qui fait quon ne peut pas « remplir les trous » en mémoire. Dominic Genest, 2009

Listes chaînées C typedef struct nœud { Etudiant etudiant; struct nœud *suivant; } Noeud; typedef struct { Nœud *premier; } Universite; CodeErreur initUniversite(Universite *u); void detruitUniversite(Universite *u); CodeErreur ajoutUniversite(Universite *u, Etudiant et); int age_selon_nom(const Universite *u, char const *nom); C++ typedef struct { Universite(); ~Universite(); void ajout(Etudiant et); int age_selon_nom(char const *nom) const; private: struct Nœud // Struct interne { Etudiant etudiant; Nœud *suivant; }; Nœud *premier; } Universite; Dominic Genest, 2009

Listes chaînées Le champ « premier » contient ladresse-mémoire du nœud correspondant au premier élément de la liste. Cest son point dentrée. Le champ « suivant » de chaque nœud contient ladresse- mémoire du nœud suivant de la liste. Le champ « suivant » du dernier nœud de la liste contient zéro. Cela marque la fin de la liste et cest la plupart du temps ce qui sera vérifié dans la condition darrêt des boucles qui seront faites sur les listes chaînées. Quand le champ « premier » vaut zéro, cela signifie que la liste est vide. Parfois, dans certaines implémentations (cest le cas souvent dans la STL), un nœud supplémentaire artificiel est toujours ajouté au début de la liste afin doptimiser certains traitements. On appelle ce nœud « nœud factice » et toutes les fonctions doivent considérer quil ne fait pas partie de la liste pour vrai. Dominic Genest, 2009

Listes chaînées CodeErreur initUniversite(Universite *u) { u->premier=0; return Ok; } CodeErreur ajoutUniversite(Universite *u, Etudiant et) { // Disons quon ajoute au début Nœud *nouveau_noeud = malloc(sizeof(Nœud)); if(!nouveau_noeud) return Erreur; nouveau_noeud->etudiant = et; nouveau_noeud->suivant = u- >premier; u->premier = nouveau_noeud; return OK; } void detruitUniversite(Universite *u) { Nœud *i = u->premier; while(i) // Équivalent à while(i!=0) { Nœud *a_supprimer = i; i=i->suivant; free(a_supprimer); } Dominic Genest, 2009

Organisation en mémoire dune liste chaînée Nœud *nouveau_noeud = malloc(sizeof(Nœud)); if(!nouveau_noeud) return Erreur; nouveau_noeud->etudiant = et; nouveau_noeud->suivant = u->premier; u->premier = nouveau_noeud; Dominic Genest, suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, premier Universite

Représentation des pointeurs par des flèches Pour alléger laspect visuel de tels schémas, on peut remplacer les nombres par des flèches dont la pointe indique ladresse-mémoire en question. Le départ de la flèche est à lintérieur du rectangle représentant le pointeur. On représentera la valeur zéro par une ligne diagonale. Par contre, il ne faut pas que cela porte à croire quun quelconque lien spécial entre le pointeur et lendroit pointé est considéré par les ordinateurs. La réalité, cest que le contenu dun pointeur demeure un simple nombre. Dominic Genest, 2009 suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, premier Universite

Ajout dans une liste chaînée Nœud *nouveau_noeud = malloc(sizeof(Nœud)); if(!nouveau_noeud) return Erreur; nouveau_noeud->etudiant = et; nouveau_noeud->suivant = u->premier; u->premier = nouveau_noeud; Dominic Genest, 2009 suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, premier Universite suivantetudiant Noeud Dominic, 31,

Listes chaînées int age_selon_nom(const Universite *u, const char *nom) { Nœud *i; for(i=u->premier;i && strcmp(nom,i- >etudiant.nom)!=0; i=i->suivant); // « ; »: Boucle vide! return i ? i->etudiant.age : -1; } Dominic Genest, 2009

Listes doublement chaînées Les listes doublement chaînées sont construites de la même façon, mais chaque nœud possède aussi un autre champ qui contient ladresse-mémoire du nœud précédent. Dominic Genest, 2009 suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, premier Universite precedent dernier

Listes doublement chaînées Pour le point dentrée dune liste simplement chaînée, nous avions une structure qui contenait ladresse-mémoire du premier nœud. Avec une liste doublement chaînée, ce nest plus nécessaire. Le point dentrée peut être ladresse- mémoire de nimporte quel nœud de la liste. Parfois, on optera quand même pour deux points dentrée, soit les adresses-mémoire du premier nœud et du dernier noeud. Dominic Genest, 2009

Les listes doublement chaînées Dans une liste simplement chaînée, si nous voulions insérer un nœud à une position arbitraire, nous devions obligatoirement avoir ladresse-mémoire du nœud précédent. Dans une liste doublement chaînée, on peut aussi le faire à partir de ladresse-mémoire du nœud suivant. Nous pouvons aussi supprimer un nœud à partir de son adresse seule. Dominic Genest, 2009

Suppression dun nœud dune liste doublement chaînée typedef struct nœud { Etudiant et; struct nœud *suiv,*prec; } Nœud; typedef struct { Nœud *premier,*dernier; } Universite; void supprimer(Universite *u, Nœud *n); Dominic Genest, 2009

Suppression dun nœud dune liste doublement chaînée void supprimer(Universite *u, Nœud *n) { if(n->prec) n->prec->suiv = n->suiv; if(n->suiv) n->suiv->prec = n->prec; if(u->premier==n) u->premier=n->suiv; if(u->dernier==n) u->dernier=n->prec; free(n); } Dominic Genest, 2009 suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, suivantetudiant Noeud Dominic, 31, premier Universite precedent dernier precedent n

Listes circulaires Dans une liste circulaire, plutôt que davoir 0 comme valeur dans le champ « suivant » du dernier nœud, on a ladresse-mémoire du premier nœud. Et dans une liste circulaire doublement chaînée, plutôt que davoir 0 comme valeur dans le champ « précédent » du premier nœud, on a ladresse- mémoire du dernier nœud. Dans ce cas, il faut faire attention, lors des itérations pour les recherches, de ne pas boucler à linfini. Il faut mémoriser ladresse-mémoire du nœud où on a commencé litération, et sorganiser pour interrompre litération dès quon y revient. Dominic Genest, 2009

Listes chaînées versus tableaux Tableaux (dynamiques ou statiques) Laccès à un élément selon son index (numéro) est instantané Linsertion ou la suppression au début ou à la fin peut se faire de façon instantanée. Linsertion ou la suppression à une position quelconque nécessite un décalage. Les pointeurs vers des éléments peuvent devenir invalides après une suppression dun autre élément, ou un ajout. Les éléments sont tous dans le même bloc en mémoire, ce qui peut aider à optimiser les accès mémoire. Listes chaînées Laccès à un élément selon son index (numéro) nécessite une itération Linsertion ou la suppression au début ou à la fin peut se faire de façon instantanée. Linsertion ou la suppression à une position quelconque peut se faire de façon instantanée (pourvu quon ait déjà trouvé le point où un veut faire lopération). Les pointeurs vers des éléments restent toujours valides même après une suppression dun autre élément, ou un ajout. Les éléments peuvent être dispersés en mémoire, donc les manipulation de mémoire peuvent être plus coûteux. Dominic Genest, 2009