cours 5 listes modi ables -...

54
Mlist Listes doublement chaˆ ın´ ees Files Conception de structures de donn´ ees Cours 5 Listes modifiables 5 avril 2013 Struct 1/31

Upload: doanthien

Post on 13-Sep-2018

223 views

Category:

Documents


0 download

TRANSCRIPT

Mlist Listes doublement chaınees Files

Conception de structures de donnees

Cours 5

Listes modifiables

5 avril 2013

Struct 1/31

Mlist Listes doublement chaınees Files

Listes modifiables

Struct 2/31

Mlist Listes doublement chaınees Files

Listes modifiables vs. listes recursives

Listes recursives (Rlist)

fonctions recursives

pas de fonction de modification

actions possibles uniquement sur le 1er element

Consequence : pour modifier une liste, il faut la reconstruire !

Exemple : supprimer toutes les occurrence de e dans la liste l

.

Struct 3/31

Mlist Listes doublement chaınees Files

Listes modifiables vs. listes recursives

Listes recursives (Rlist)

fonctions recursives

pas de fonction de modification

actions possibles uniquement sur le 1er element

Consequence : pour modifier une liste, il faut la reconstruire !

Exemple : supprimer toutes les occurrence de e dans la liste l

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)) );

}

Struct 3/31

Mlist Listes doublement chaınees Files

Listes modifiables : type Mlist

typedef ... Element; // type des elements 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);

Struct 4/31

Mlist Listes doublement chaınees Files

Fonctions de modification des listes chaınees

void insertFirst(Element e, Mlist *l); // insere en tete

void insertAfter(Element e, Cell *c); // insere ensuite

void insertLast(Element e, Mlist *l); // insere en fin

void insertPosition(Element e, Mlist *l, int pos);

// insere a une position donnee

Element deleteFirst(Mlist *l); // supprime en tete

Element deleteAfter(Cell *c); // supprime ensuite

Element deleteLast(Mlist *l); // supprime en fin

Element deletePosition(Mlist *l, int pos);

// supprime a une position donnee

Attention : toutes ces fonctions modifient les listes !

Struct 5/31

Mlist Listes doublement chaınees Files

Listes modifiables vs. recursives (suite)

Listes recursives (Rlist)

fonctions recursives

pas de fonction de modification

actions possibles uniquement sur le 1er element

Consequence : pour modifier une liste, il faut la reconstruire !

Listes modifiables

fonctions iteratives (boucles)

fonctions de modifications

actions possibles sur n’importe quel element

Attention : ces fonctions sont plus complexes a implanter !

Struct 6/31

Mlist Listes doublement chaınees Files

Listes modifiables vs. recursives (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);

}

}Struct 7/31

Mlist Listes doublement chaınees Files

Insertion en tete

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

l *l

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

e

new

l *l

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

e

l

new*l=

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

l *l

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

e

new

l *l

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

e

lnew*l =

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

e

new

l

l *l

*l

*l

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

e

new

l

*l

l

=

Struct 8/31

Mlist Listes doublement chaınees Files

Insertion apres une cellule

Struct 9/31

Mlist Listes doublement chaınees Files

Insertion apres une cellule

17 14

c

Struct 9/31

Mlist Listes doublement chaınees Files

Insertion apres une cellule

17 14

e

c

new

Struct 9/31

Mlist Listes doublement chaınees Files

Insertion apres une cellule

17 14

e

c

new

Struct 9/31

Mlist Listes doublement chaınees Files

Manipulation de listes chaınees

void insertFirst(Element e, Mlist *l){

Cell *new=cons(e,*l);

*l=new;

}

/* insere une cellule contenant e apres 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ınees Files

Manipulation de listes chaınees - 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);

}

}

Struct 11/31

Mlist Listes doublement chaınees Files

Manipulation de listes chaınees - suite

Element deleteFirst(Mlist *l){

if(isEmpty(*l))

error("deleteFirst impossible!");

Element e=car(*l);

*l=cdr(*l);

return e;

}

/* detruit 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;

}

Struct 12/31

Mlist Listes doublement chaınees Files

Manipulation de listes chaınees - suite

Element deleteLast(Mlist *l){

if(isEmpty(*l))

error("deleteLast impossible!");

if(isEmpty(cdr(*l))) /* la liste a 1 seul element */

return deleteFirst(l);

else{

Mlist tmp=*l;

while(!isEmpty(cdr(cdr(tmp))))

tmp=cdr(tmp);

return deleteAfter(tmp);

}

}

Struct 13/31

Mlist Listes doublement chaınees Files

Complexites comparees

Complexite Complexite

Operation tableau liste

Acces au ie element O(1) ? ?

Insertion en tete e O(n) ? ?

Insertion apres un element O(n) ? ?

Insertion en fin e O(1) ? ?

Suppression en tete e O(n) ? ?

Suppression apres un element O(n) ? ?

Suppression en fin O(1) ? ?

Manipulations des tableaux et des listes, complexite desoperations preservant l’ordre relatif des elements.

Struct 14/31

Mlist Listes doublement chaınees Files

Complexites comparees

Complexite Complexite

Operation tableau liste

Acces au ie element O(1) O(n)

Insertion en tete e O(n) O(1)

Insertion apres un element O(n) O(1)

Insertion en fin e O(1) O(n)

Suppression en tete e O(n) O(1)

Suppression apres un element O(n) O(1)

Suppression en fin O(1) O(n)

Manipulations des tableaux et des listes, complexite desoperations preservant l’ordre relatif des elements.

Struct 14/31

Mlist Listes doublement chaınees Files

Listes doublement chaınees

Struct 15/31

Mlist Listes doublement chaınees Files

Simplement chaınee vs. doublement chaınee

Points communs :

Structures permettant de stocker une collection de donneesde meme type.

L’espace memoire utilise n’est pas contigu.

La taille est inconnue a priori ;

Une liste doublement chaınee est constituee de cellulesqui sont liees entre elles par des pointeurs.

Pour acceder a un element quelconque d’une liste, il fautparcourir la liste jusqu’a cet element.

Differences :

Une liste doublement chaınee n’est PAS recursive !

On peut acceder directement au premier et dernier element.

On peut parcourir la liste dans les 2 sens (on peut doncrevenir en arriere).

Struct 16/31

Mlist Listes doublement chaınees Files

Representation graphique

liste vide:

liste contenant 1 élément:

liste contenant 3 éléments:

first last first last

3

17 14

first last

Struct 17/31

Mlist Listes doublement chaınees Files

Definition d’une liste doublement chaınee 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 precedente */

}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ınees Files

Definition d’une liste doublement chaınee - suite

int isEmptyDList(DList l){

if( (l.first==NULL && l.last!=NULL) ||

(l.first!=NULL && l.last==NULL))

error("DList mal formee!");

/* n’arrive pas si la DList est utilisee 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 ratee!");

c->elem=e;

c->next=nxt;

c->prev=prv;

return c;

}

Struct 19/31

Mlist Listes doublement chaınees Files

Manipulation de listes doublement chaınees

Fonctions pour inserer ou supprimer des elements dans une listedoublement chaınee :

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 !

Struct 20/31

Mlist Listes doublement chaınees Files

Insertion en tete

Struct 21/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

lastfirst

Struct 21/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

last

28new

first

Struct 21/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

lastfirst

28new

Struct 21/31

Mlist Listes doublement chaınees Files

Insertion en tete

17 14

lastfirst

28new

Struct 21/31

Mlist Listes doublement chaınees Files

Insertion a la place d’une cellule

Struct 22/31

Mlist Listes doublement chaınees Files

Insertion a la place d’une cellule

17 14

lastfirst c

Struct 22/31

Mlist Listes doublement chaınees Files

Insertion a la place d’une cellule

17 14

lastfirst

28new

c

Struct 22/31

Mlist Listes doublement chaınees Files

Insertion a la place d’une cellule

17 14

lastfirst

28new

c

Struct 22/31

Mlist Listes doublement chaınees Files

Insertion a la place d’une cellule

17 14

lastfirst

28new

c

Struct 22/31

Mlist Listes doublement chaınees Files

Manipulation de listes doublement chaınees - 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!");

}Struct 23/31

Mlist Listes doublement chaınees Files

Manipulation de listes doublement chaınees - 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 meme 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;

}

Struct 24/31

Mlist Listes doublement chaınees Files

Manipulation de listes doublement chaınees - 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

Mlist Listes doublement chaınees Files

Manipulation de listes doublement chaınees - 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 ou supprimer */

if(pos!=0) /* c-a-d tmp->next==NULL */

error("deletePosition impossible!");

return delete(tmp, l);

}

}

Struct 26/31

Mlist Listes doublement chaınees Files

Complexites comparees

Complexite

Operation tableau liste liste d.c.

Acces au ie element O(1) O(n)

Insertion en tete O(n) O(1)

Insertion au niveau d’1 element O(n) O(1)

Insertion en fin O(1) O(n)

Suppression en tete O(n) O(1)

Suppression au niveau d’1 element O(n) O(1)

Suppression en fin O(1) O(n)

Manipulations des tableaux et des listes, complexite desoperations preservant l’ordre relatif des elements.

Struct 27/31

Mlist Listes doublement chaınees Files

Complexites comparees

Complexite

Operation tableau liste liste d.c.

Acces au ie element O(1) O(n) O(n)

Insertion en tete O(n) O(1) O(1)

Insertion au niveau d’1 element O(n) O(1) O(1)

Insertion en fin O(1) O(n) O(1)

Suppression en tete O(n) O(1) O(1)

Suppression au niveau d’1 element O(n) O(1) O(1)

Suppression en fin O(1) O(n) O(1)

Manipulations des tableaux et des listes, complexite desoperations preservant l’ordre relatif des elements.

Struct 27/31

Mlist Listes doublement chaınees Files

L’exemple des files

Struct 28/31

Mlist Listes doublement chaınees Files

Qu’est-ce qu’une file ?

Une file (queue) est une structure de donnees fondee sur leprincipe “premier arrive, premier sorti” (FIFO : First In, FirstOut). Les premiers elements ajoutes a la file sont les premiers aetre recuperes (penser a une file d’attente, par exemple).

On peut acceder au premier element (le prochain a sortirnextOut) et au dernier element (le dernier arrive prevIn).

On peut defiler le premier element (removeFromFifo).

On peut enfiler un element a la fin (insertInFifo).

Il faut pouvoir detecter si elle est vide (et eventuellementsi elle est pleine).

Il est possible d’implanter des files en C en utilisant destableaux, des listes ou des listes doublement chaınees.

Struct 29/31

Mlist Listes doublement chaınees Files

FIFO : Complexites comparees

Complexite

Operation 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 decalages : nombre d’elements limite

Tableaux sans decalages : nombre d’ajouts limite

Struct 30/31

Mlist Listes doublement chaınees Files

Definir une file comme liste doublement chaınee

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’element dans une file vide!");

return deleteLast(f);

}

Element prevIn(Fifo f){

if(isEmptyFifo(f)) error("pas d’element dans une file vide!");

return (f.first)->elem;

}

Element nextOut(Fifo f){

if(isEmptyFifo(f)) error("pas d’element dans une file vide!");

return (f.last)->elem;

}Struct 31/31