Conception de structures de donn´ ees
Cours 5 Listes modifiables
5 avril 2013
Struct 1/31
Listes modifiables
Struct 2/31
Mlist Listes doublement chaˆın´ees Files
Listes modifiables vs. listes r´ ecursives
Listes r´ecursives (Rlist) fonctions r´ecursives
pas de fonction de modification
actions possibles uniquement sur le 1er ´el´ement
Cons´equence : pour modifier une liste, il faut la reconstruire ! Exemple : supprimer toutes les occurrence de e dans la listel
.
Mlist Listes doublement chaˆın´ees Files
Listes modifiables : type Mlist
typedef ... Element; // type des ´el´ements de la liste typedef struct cell{ // type des maillons de la liste
Element elem;
struct cell *next;
}Cell;
typedef Cell *Mlist; // type d’une liste (pointeur sur maillon)
Mlist newEmptyMlist(void);
int isEmpty(Mlist l);
Mlist cons(Element e, Mlist nxt);
Element car(Mlist l);
Mlist cdr(Mlist l);
Fonctions de modification des listes chaˆın´ ees
void insertFirst(Element e, Mlist *l); // ins`ere en t^ete void insertAfter(Element e, Cell *c); // ins`ere ensuite void insertLast(Element e, Mlist *l); // ins`ere en fin void insertPosition(Element e, Mlist *l, int pos);
// ins`ere `a une position donn´ee
Element deleteFirst(Mlist *l); // supprime en t^ete Element deleteAfter(Cell *c); // supprime ensuite Element deleteLast(Mlist *l); // supprime en fin Element deletePosition(Mlist *l, int pos);
// supprime `a une position donn´ee
Attention : toutes ces fonctions modifientles listes !
Struct 5/31
Listes modifiables vs. r´ ecursives (suite)
Listes r´ecursives (Rlist) fonctions r´ecursives
pas de fonction de modification
actions possibles uniquement sur le 1er ´el´ement
Cons´equence : pour modifier une liste, il faut la reconstruire !
Listes modifiables
fonctions it´eratives (boucles) fonctions de modifications
actions possibles sur n’importe quel ´el´ement
Attention : ces fonctions sont plus complexes `a implanter !
Struct 6/31
Mlist Listes doublement chaˆın´ees Files
Listes modifiables vs. r´ ecursives (fin)
Rlist deleteAllOcc(Element e, Rlist l){
if(isEmpty(l))
return newEmptyRlist();
else if( car(l) == e )
return deleteAllOcc(e,cdr(l));
else return cons( car(l), deleteAllOcc(e,cdr(l)) );
} // reconstruction!
--- void deleteAllOcc(Element e, Mlist *l){ // param: pointeur sur liste!
if(!isEmpty(*l)){
Mlist tmp=*l; // pointeur de parcours while(!isEmpty(cdr(tmp))){
if(car(cdr(tmp))==e) deleteAfter(tmp);
else tmp=cdr(tmp); // parcours sans reconstruction!
}
if( car(*l) == e ) deleteFirst(l);
} }
Mlist Listes doublement chaˆın´ees Files
Insertion en tˆ ete
Insertion apr` es une cellule
Struct 9/31
Manipulation de listes chaˆın´ ees
void insertFirst(Element e, Mlist *l){
Cell *new=cons(e,*l);
*l=new;
}
/* ins`ere une cellule contenant e apr`es la cellule c */
void insertAfter(Element e, Cell *c){
if(isEmpty(c)) error("insertAfter impossible!");
Cell *new=cons(e,cdr(c));
c->next=new;
}
Struct 10/31
Mlist Listes doublement chaˆın´ees Files
Manipulation de listes chaˆın´ ees - suite
void insertPosition(Element e, Mlist *l, int pos){
if(pos==0)
insertFirst(e,l);
else{
Mlist tmp=*l;
while(!isEmpty(tmp) && pos!=1){
tmp=cdr(tmp);
pos--;
}
if(pos!=1)
error("insertPosition impossible!");
else insertAfter(e,tmp);
} }
Mlist Listes doublement chaˆın´ees Files
Manipulation de listes chaˆın´ ees - suite
Element deleteFirst(Mlist *l){
if(isEmpty(*l))
error("deleteFirst impossible!");
Element e=car(*l);
*l=cdr(*l);
return e;
}
/* d´etruit la cellule suivant c */
Element deleteAfter(Cell *c){
if( isEmpty(c) || isEmpty(cdr(c)) ) error("deleteAfter impossible!");
Element e=car(cdr(c));
c->next=cdr(cdr(c));
return e;
}
Manipulation de listes chaˆın´ ees - suite
Element deleteLast(Mlist *l){
if(isEmpty(*l))
error("deleteLast impossible!");
if(isEmpty(cdr(*l))) /* la liste a 1 seul ´el´ement */
return deleteFirst(l);
else{
Mlist tmp=*l;
while(!isEmpty(cdr(cdr(tmp)))) tmp=cdr(tmp);
return deleteAfter(tmp);
} }
Struct 13/31
Complexit´ es compar´ ees
Complexit´e Complexit´e
Op´eration tableau liste
Acc`es au ie ´el´ement O(1) ? ?
Insertion en tˆete e O(n) ? ?
Insertion apr`es un ´el´ement O(n) ? ?
Insertion en fin e O(1) ? ?
Suppression en tˆete e O(n) ? ?
Suppression apr`es un ´el´ement O(n) ? ?
Suppression en fin O(1) ? ?
Manipulations des tableaux et des listes, complexit´e des op´erations pr´eservant l’ordre relatif des ´el´ements.
Struct 14/31
Mlist Listes doublement chaˆın´ees Files
Listes doublement chaˆın´ ees
Mlist Listes doublement chaˆın´ees Files
Simplement chaˆın´ ee vs. doublement chaˆın´ ee
Points communs :
Structures permettant de stocker une collection de donn´ees de mˆeme type.
L’espace m´emoire utilis´e n’est pas contigu.
La taille est inconnue `a priori ;
Une liste doublement chaˆın´ee est constitu´ee de cellules qui sont li´ees entre elles par des pointeurs.
Pour acc´eder `a un ´el´ement quelconqued’une liste, il faut parcourir la liste jusqu’`a cet ´el´ement.
Diff´erences :
Une liste doublement chaˆın´ee n’est PAS r´ecursive!
On peut acc´eder directement au premieret dernier´el´ement.
On peut parcourir la liste dans les 2 sens(on peut donc revenir en arri`ere).
Repr´ esentation graphique
liste vide:
liste contenant 1 élément:
liste contenant 3 éléments:
first last first last
3
17 1
4
first last
Struct 17/31
D´ efinition d’une liste doublement chaˆın´ ee en C
typedef int Element;
typedef struct cell{
Element elem;
struct cell *next; /* pointeur vers la cellule suivante */
struct cell *prev; /* pointeur vers la cellule pr´ec´edente */
}Cell;
typedef struct{ /* attention, une DList n’est pas un pointeur! */
Cell *first;
Cell *last;
} DList;
DList newEmptyDList(void){
return (DList){NULL,NULL};
}
Struct 18/31
Mlist Listes doublement chaˆın´ees Files
D´ efinition d’une liste doublement chaˆın´ ee - suite
int isEmptyDList(DList l){
if( (l.first==NULL && l.last!=NULL) ||
(l.first!=NULL && l.last==NULL)) error("DList mal form´ee!");
/* n’arrive pas si la DList est utilis´ee correctement */
return l.first==NULL; /* ou l.last==NULL */
}
Cell *newCell(Cell *prv, Element e, Cell *nxt){
Cell *c;
if ((c=(Cell *)malloc(sizeof(Cell)))==NULL) error("Allocation rat´ee!");
c->elem=e;
c->next=nxt;
c->prev=prv;
return c;
}
Mlist Listes doublement chaˆın´ees Files
Manipulation de listes doublement chaˆın´ ees
Fonctions pour ins´erer ou supprimer des ´el´ements dans une liste doublement chaˆın´ee :
void insertFirst(Element e, DList *l);
void insert(Element e, Cell *c, DList *l);
void insertLast(Element e, DList *l);
void insertPosition(Element e, int pos, DList *l);
Element deleteFirst(DList *l);
Element delete(Cell *c, DList *l);
Element deleteLast(DList *l);
Element deletePosition(DList *l, int pos);
Attention : ces fonctions modifient les listes ; elles ne fabriquent pas des copies!
Insertion en tˆ ete
Struct 21/31
Insertion ` a la place d’une cellule
Struct 22/31
Mlist Listes doublement chaˆın´ees Files
Manipulation de listes doublement chaˆın´ ees - 1
void insertFirst(Element e, DList *l){
Cell *new=newCell(NULL,e,l->first);
if(!isEmptyDList(*l)) (l->first)->prev=new;
else l->last=new; /* 1 cellule: first=last */
l->first=new;
}
void insert(Element e, Cell *c, DList *l){
if(c==l->first) insertFirst(e,l);
else /* c==l->last n’est pas un cas particulier */
if(!isEmptyDList(*l) && c!=NULL){
Cell *new=newCell(c->prev,e,c);
c->prev=new;
(new->prev)->next=new;
}
else error("insert impossible!");
}
Mlist Listes doublement chaˆın´ees Files
Manipulation de listes doublement chaˆın´ ees - 2
void insertLast(Element e, DList *l){
Cell *new=newCell(l->last,e,NULL);
if(!isEmptyDList(*l)) (l->last)->next=new;
else l->first=new;
l->last=new;
} /* exactement le m^eme principe que insertFirst */
Element deleteFirst(DList *l){
if(isEmptyDList(*l))
error("deleteFirst impossible!");
Element e=(l->first)->elem; /* sauvegarde */
l->first=(l->first)->next;
if(l->first==NULL) l->last=NULL;
else (l->first)->prev=NULL;
return e;
}
Manipulation de listes doublement chaˆın´ ees - 3
Element delete(Cell *c, DList *l){
if(c==NULL || isEmptyDList(*l)) error("delete impossible!");
if(c==l->first) /* ou c->prev==NULL */
l->first=c->next;
if(c==l->last) /* ou c->next==NULL */
l->last=c->prev;
Element e=c->elem; /* sauvegarde */
if(c->next!=NULL)
(c->next)->prev=c->prev;
if(c->prev!=NULL)
(c->prev)->next=c->next;
return e;
}
Struct 25/31
Manipulation de listes doublement chaˆın´ ees - 4
Element deletePosition(DList *l, int pos){
if(isEmptyDList(*l))
error("deletePosition impossible!");
if(pos==0)
return deleteFirst(l);
else{
Cell *tmp=l->first;
while(tmp->next!=NULL && pos!=0){ tmp=tmp->next;
pos--;
} /* recherche de l’endroit o`u supprimer */
if(pos!=0) /* c-`a-d tmp->next==NULL */
error("deletePosition impossible!");
return delete(tmp, l);
} }
Struct 26/31
Mlist Listes doublement chaˆın´ees Files
Complexit´ es compar´ ees
Complexit´e
Op´eration tableau liste liste d.c.
Acc`es au ie ´el´ement O(1) O(n)
Insertion en tˆete O(n) O(1)
Insertion au niveau d’1 ´el´ement O(n) O(1)
Insertion en fin O(1) O(n)
Suppression en tˆete O(n) O(1)
Suppression au niveau d’1 ´el´ement O(n) O(1)
Suppression en fin O(1) O(n)
Manipulations des tableaux et des listes, complexit´e des op´erations pr´eservant l’ordre relatif des ´el´ements.
Mlist Listes doublement chaˆın´ees Files
L’exemple des files
Qu’est-ce qu’une file ?
Une file (queue) est une structure de donn´ees fond´ee sur le principe “premier arriv´e, premier sorti” (FIFO : First In, First Out). Les premiers ´el´ements ajout´es `a la file sont les premiers `a ˆetre r´ecup´er´es (penser `a une file d’attente, par exemple).
On peut acc´eder au premier ´el´ement (le prochain `a sortir nextOut) et au dernier ´el´ement (le dernier arriv´eprevIn).
On peut d´efiler le premier ´el´ement (removeFromFifo).
On peut enfiler un ´el´ement `a la fin (insertInFifo).
Il faut pouvoir d´etectersi elle est vide (et ´eventuellement si elle est pleine).
Il est possible d’implanter des files en C en utilisant des tableaux, des listes ou des listes doublement chaˆın´ees.
Struct 29/31
FIFO : Complexit´ es compar´ ees
Complexit´e
Op´eration tableau liste liste d.c.
next out O(1) O(1) O(1) O(1)
previous in O(1) O(1) O(n) O(1) insert in Fifo O(1) O(1) O(n) O(1) remove from Fifo O(n) O(1) O(1) O(1)
Tableaux avec d´ecalages : nombre d’´el´ements limit´e Tableaux sans d´ecalages : nombre d’ajouts limit´e
Struct 30/31
Mlist Listes doublement chaˆın´ees Files
D´ efinir une file comme liste doublement chaˆın´ ee
typedef DList Fifo;
int isEmptyFifo(Fifo f){ return isEmptyDList(f); } Fifo newEmptyFifo(void){ return createEmptyDList(); } void insertInFifo(Element e, Fifo* f){ insertFirst(e,f); } Element removeFromFifo(Fifo* f){
if(isEmptyFifo(*f)) error("pas d’´el´ement dans une file vide!");
return deleteLast(f);
}
Element prevIn(Fifo f){
if(isEmptyFifo(f)) error("pas d’´el´ement dans une file vide!");
return (f.first)->elem;
}
Element nextOut(Fifo f){
if(isEmptyFifo(f)) error("pas d’´el´ement dans une file vide!");
return (f.last)->elem;
}