Listes Listes chaınees en C Piles
Conception de structures de donnees
Cours 4
Listes recursives
25 mars 2013
Struct 1/21
Listes Listes chaınees en C Piles
Listes recursives
Struct 2/21
Listes Listes chaınees en C Piles
Qu’est-ce qu’une liste ?
Une liste est une structure permettant de stocker unecollection de donnees de meme type.
Definition recursive : une liste de donnees est :
soit vide,soit une donnee suivie d’une liste de donnees.
Contrairement aux tableaux, l’espace memoire utilise par uneliste n’est pas contigu.
La taille d’une liste est inconnue a priori ; elle peut contenirautant d’elements que l’on veut.
On ne peut acceder directement qu’au 1er element d’une liste.
Pour acceder au ie element d’un liste , il faut parcourir tousles elements de la liste jusqu’au ie.
Les listes definies ci-dessous ne sont PAS MODIFIABLES !
Struct 3/21
Listes Listes chaınees en C Piles
Type abstrait Rlist
typedef ... Element;typedef ... Rlist;
// renvoie une liste vide
Rlist newEmptyRlist(void);
// teste si la liste est vide (renvoie 1 si elle est vide, et 0 sinon)
int isEmpty(Rlist l);
// cree une liste dont le 1er element est e et dont la suite est nxt;
// erreur si l’allocation memoire de la nouvelle cellule echoue.
Rlist cons(Element e, Rlist nxt);
// renvoie le 1er element de la Rliste l, si celle-ci n’est pas vide;
// provoque une erreur si la liste est vide.
Element car(Rlist l);
// renvoie la suite de la Rliste l, si celle-ci n’est pas vide;
// provoque une erreur si la liste est vide.
Rlist cdr(Rlist l);
Struct 4/21
Listes Listes chaınees en C Piles
Exemple d’utilisation d’une liste
void printRlist(Rlist l, char *fmt);
int main(void){
Rlist rl = newEmptyRlist();
printRlist(rl,"%d");
rl = cons(1,rl);
rl = cons(2,cons(3,rl));
printRlist(rl,"%d");
printf("%d\n",car(rl));
printf("%d\n",car(cdr(rl)));
printRlist(cdr(rl),"%d");
printRlist(cdr(cdr(rl)),"%d");
rl = cdr(rl);
printRlist(rl,"%d");
printf("%d\n",car(cdr(cdr(rl))));
return 0;
}
Struct 5/21
Listes Listes chaınees en C Piles
Exemple d’utilisation d’une liste
void printRlist(Rlist l, char *fmt);
int main(void){
Rlist rl = newEmptyRlist();
printRlist(rl,"%d"); ---------------> [ ]
rl = cons(1,rl);
rl = cons(2,cons(3,rl));
printRlist(rl,"%d"); ---------------> [ 2 3 1 ]
printf("%d\n",car(rl)); ------------> 2
printf("%d\n",car(cdr(rl))); -------> 3
printRlist(cdr(rl),"%d"); ----------> [ 3 1 ]
printRlist(cdr(cdr(rl)),"%d"); -----> [ 1 ]
rl = cdr(rl);
printRlist(rl,"%d"); ---------------> [ 3 1 ]
printf("%d\n",car(cdr(cdr(rl)))); --> erreur!
return 0;
}
Struct 5/21
Listes Listes chaınees en C Piles
Manipulation recursive des listes
2 (principaux) types de fonctions recursives sur les listes :
B Les fonctions qui parcourent une liste :
/* type */ scanRec(Rlist l){
if( isEmpty(l) ) /* ou presque vide */
return /* valeur du cas d’arret */
else
return /* une combinaison de car(l) et de scanRec( cdr(l) )*/
}
B Les fonctions qui construisent une liste :
Rlist buildRec( /* param */ ){
if( /* cas d’arret */ )
return /* liste vide ou presque vide */
else
return cons( /* 1er */ , buildRec( /* liste + petite */ ) );
}
Struct 6/21
Listes Listes chaınees en C Piles
Exemples de fonctions (recursives) sur les listes
int sumRlist(Rlist l); /* somme des elements de l*/
int nbOcc(Element e, Rlist l); /* nombre d’occurrences de e dans l */
Rlist member(Element e, Rlist l); /* teste si e appartient a l */
Rlist copyRlist(Rlist l); /* copie la liste l* /
Rlist copyAndAppend(Rlist l1, Rlist l2);
/* renvoie une copie de la conatenation de l1 et l2 */
Rlist arrayToRlist(Element *tab, int lg);
/* transforme un tableau en liste */
Rlist arrayToInvRlist(Element *tab, int lg);
/* transforme un tableau en liste inversee */
Struct 7/21
Listes Listes chaınees en C Piles
Fonctions qui prennent des listes en parametreint sumRlist(Rlist l){ /* somme des elements de l*/
if(isEmpty(l))
return 0;
else return car(l) + sumRlist(cdr(l));
}
int nbOcc(Element e, Rlist l){ /* nombre d’occurrences de e dans l*/
if(isEmpty(l))
return 0;
else if( car(l)==e )
return 1 + nbOcc(e,cdr(l));
else return nbOcc(e,cdr(l));
}
Rlist member(Element e, Rlist l){ /* teste si e appartient a l*/
if(isEmpty(l))
return newEmptyRlist();
else if( car(l)==e )
return l;
else return member(e,cdr(l));
}Struct 8/21
Listes Listes chaınees en C Piles
Fonctions qui renvoient des listes
Rlist copyRlist(Rlist l){
if(isEmpty(l)) return newEmptyRlist();
else return cons(car(l),copyRlist(cdr(l)));
}
Rlist copyAndAppend(Rlist l1, Rlist l2){
if(isEmpty(l1)) return copyRlist(l2);
else return cons(car(l1),copyAndAppend(cdr(l1),l2));
}
Rlist arrayToRlist(Element *tab, int lg){
if(lg==0) return newEmptyRlist();
else return cons(tab[0],arrayToRlist(tab+1,lg-1));
}
Rlist arrayToInvRlist(Element *tab, int lg){
if(lg==0) return newEmptyRlist();
else return cons(tab[lg-1],arrayToInvRlist(tab,lg-1));
}
Struct 9/21
Listes Listes chaınees en C Piles
Implantation des listes en C
→ Les Listes Chaınees
Struct 10/21
Listes Listes chaınees en C Piles
Structure d’une liste chaınee
Une liste chaınee est constitue de cellules qui contiennent unedonnee et un pointeur vers la suite de la liste.
17
3
14
liste vide
liste contenant 1 élément
liste contenant 3 éléments
Struct 11/21
Listes Listes chaınees en C Piles
Definition d’une liste chaınee d’entiers en C
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 *Rlist; // type d’une liste (pointeur sur maillon)
Rlist newEmptyRlist(void){ // cree une nouvelle liste vide
return (Rlist)NULL;
}
int isEmpty(Rlist l){ // teste si la liste est vide
return (l==NULL);
}
Struct 12/21
Listes Listes chaınees en C Piles
Manipulation d’une liste chaınee d’entiers en C
Rlist cons(Element e, Rlist nxt){ // constructeur
Cell *c;
if ( (c=(Cell *)malloc(sizeof(Cell))) == NULL ) error("...");
c->elem=e;
c->next=nxt;
return c;
}
Element car(Rlist l){ // 1er element
if(isEmpty(l))
error("Pas d’elements dans une liste vide!!!");
return l->elem;
}
Rlist cdr(Rlist l){ // fin de la liste
if(isEmpty(l))
error("Pas d’elements dans une liste vide!!!");
return l->next;
}
Struct 13/21
Listes Listes chaınees en C Piles
L’exemple des piles
Struct 14/21
Listes Listes chaınees en C Piles
Qu’est-ce qu’une pile ?
Une pile (stack) est une structure de donnees fondee sur leprincipe “dernier arrive, premier sorti” (LIFO : Last In, FirstOut). Les derniers elements ajoutes a la pile sont les premiers aetre recuperes (penser a une pile d’assiettes, par exemple).
On accede a une pile uniquement par son sommet.
On peut depiler l’element au sommet (pop).
On peut poser un element au dessus du sommet (push).
On ne peut pas parcourir les elements d’une pile.
Il faut pouvoir detecter si elle est vide (et eventuellementsi elle est pleine).
Il est possible d’implanter des piles en C, soit en utilisant destableaux (hauteur bornee), soit en utilisant des listes (pas delimite de hauteur).
Struct 15/21
Listes Listes chaınees en C Piles
Le type abstrait Stack
typedef ... Stack;
Stack initStack(void); // cree une pile vide
int isEmptyStack(Stack s); // teste si la pile s est vide
int isFullStack(Stack s); // teste si la pile s est pleine
Element top(Stack s); // renvoie la valeur du sommet de s (sans depiler)
Element pop(Stack *s); // depile et renvoie la valeur du sommet de s
void push(Element e, Stack *s); // empile e au sommet de s
void freeStack(Stack *s); // libere l’espace utilise par la pile s
void emptyStack(Stack *s); // vide la pile s
Struct 16/21
Listes Listes chaınees en C Piles
Utiliser une pile pour calculer
int postValue(char *s){ // s: expression arith. postfixee
Stack S = initStack();
int i=0,val;
while(s[i]!=’\0’){ // exemple: 21-3+
switch(s[i]){
case ’+’:
val=pop(&S)+pop(&S);
push(val,&S); break;
case ’-’:
val=pop(&S); val=pop(&S)-val;
push(val,&S); break;
...
default:
push(s[i]-’0’,&S); // la valeur correspondant au caractere
}
i++;
}
return pop(&S);
}
Struct 17/21
Listes Listes chaınees en C Piles
Definir une pile comme un tableau
#define MAX 1000
typedef struct{
int max stack;
int nb elem;
Element *tab;
}Stack;
Stack initStack(void){ /* un seul malloc */
Stack res;
res.max_stack=MAX;
if ( (res.tab=malloc(res.max_stack*sizeof(Element))) == NULL )
error("Allocation ratee!");
res.nb_elem=0;
return res;
}
Struct 18/21
Listes Listes chaınees en C Piles
Definir une pile comme un tableau - suite
int isEmptyStack(Stack s){
return (s.nb_elem==0);
}
int isFullStack(Stack s){
return (s.nb_elem==s.max_stack);
}
Element top(Stack s){ /* acceder au sommet sans le depiler */
if(isEmptyStack(s))
error("pas de 1er element dans une pile vide!");
return s.tab[s.nb_elem-1];
}
Element pop(Stack *s){
if(isEmptyStack(*s))
error("pas de pop sur une pile vide!");
(s->nb_elem)--;
return s->tab[s->nb_elem];
}
Struct 19/21
Listes Listes chaınees en C Piles
Definir une pile comme un tableau - suite
void push(Element e, Stack *s){
if(isFullStack(*s))
error("pas de push sur une pile pleine!");
s->tab[s->nb_elem]=e;
(s->nb_elem)++;
}
void emptyStack(Stack *s){ /* vider la pile */
while(!isEmptyStack(*s))
pop(s);
}
void freeStack(Stack *s){
free(s->tab); /* un seul malloc -> un seul free */
s->tab=NULL;
}
Struct 20/21
Listes Listes chaınees en C Piles
en TP
Comment faire des piles avec des listes ?
Quel est l’interet ?
Calculer des expressions arithmetiques parenthesees.
Et pour faire une file ?
Struct 21/21