Conception de structures de donn´ ees
Cours 4 Listes r´ecursives
25 mars 2013
Struct 1/21
Listes r´ ecursives
Struct 2/21
Listes Listes chaˆın´ees en C Piles
Qu’est-ce qu’une liste ?
Une liste est une structure permettant de stocker une collection de donn´ees de mˆeme type.
D´efinition r´ecursive : une liste de donn´ees est :
soit vide,soit une donn´ee suivie d’une listede donn´ees.
Contrairement aux tableaux, l’espace m´emoire utilis´e par une liste n’est pas contigu.
La taille d’une liste est inconnue `a priori ; elle peut contenir autant d’´el´ements que l’on veut.
On ne peut acc´eder directement qu’au 1er ´el´ement d’une liste.
Pour acc´eder au i
e´el´ement d’un liste , il faut parcourir tous les ´el´ements de la liste jusqu’au i
e.
Les listes d´efinies ci-dessous ne sont PAS MODIFIABLES !
Listes Listes chaˆın´ees 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);
// cr´ee une liste dont le 1er ´el´ement est e et dont la suite est nxt;
// erreur si l’allocation m´emoire de la nouvelle cellule ´echoue.
Rlist cons(Element e, Rlist nxt);
// renvoie le 1er ´el´ement 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);
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
Manipulation r´ ecursive des listes
2 (principaux) types de fonctions r´ecursives 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’arr^et */
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’arr^et */ )
return /* liste vide ou presque vide */
else
return cons( /* 1er */ , buildRec( /* liste + petite */ ) );
}
Struct 6/21
Listes Listes chaˆın´ees en C Piles
Exemples de fonctions (r´ ecursives) sur les listes
int sumRlist(Rlist l); /* somme des ´el´ements 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 invers´ee */
Listes Listes chaˆın´ees en C Piles
Fonctions qui prennent des listes en param` etre
int sumRlist(Rlist l){ /* somme des ´el´ements 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));
}
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
Implantation des listes en C
→ Les Listes Chaˆın´ ees
Struct 10/21
Listes Listes chaˆın´ees en C Piles
Structure d’une liste chaˆın´ ee
Une liste chaˆın´ ee est constitu´e de cellules qui contiennent une donn´ee et un pointeur vers la suite de la liste.
17 3
1 4
liste vide
liste contenant 1 élément
liste contenant 3 éléments
Listes Listes chaˆın´ees en C Piles
D´ efinition d’une liste chaˆın´ ee d’entiers en C
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 *Rlist; // type d’une liste (pointeur sur maillon)
Rlist newEmptyRlist(void){ // cr´e´e une nouvelle liste vide return (Rlist)NULL;
}
int isEmpty(Rlist l){ // teste si la liste est vide return (l==NULL);
}
Manipulation d’une liste chaˆın´ ee 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’´el´ements dans une liste vide!!!");
return l->elem;
}
Rlist cdr(Rlist l){ // fin de la liste if(isEmpty(l))
error("Pas d’´el´ements dans une liste vide!!!");
return l->next;
}
Struct 13/21
L’exemple des piles
Struct 14/21
Listes Listes chaˆın´ees en C Piles
Qu’est-ce qu’une pile ?
Une pile (stack) est une structure de donn´ees fond´ee sur le principe “dernier arriv´e, premier sorti” (LIFO : Last In, First Out). Les derniers ´el´ements ajout´es `a la pile sont les premiers `a ˆetre r´ecup´er´es (penser `a une pile d’assiettes, par exemple).
On acc`ede `a une pile uniquement par son sommet.
On peut d´epiler l’´el´ement au sommet (pop).
On peut poser un ´el´ement au dessus du sommet (push).
On ne peut pas parcourir les ´el´ements d’une pile.
Il faut pouvoir d´etecter si elle est vide (et ´eventuellement si elle est pleine).
Il est possible d’implanter des piles en C, soit en utilisant des tableaux (hauteur born´ee), soit en utilisant des listes (pas de limite de hauteur).
Listes Listes chaˆın´ees en C Piles
Le type abstrait Stack
typedef ... Stack;
Stack initStack(void); // cr´ee 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 d´epiler) Element pop(Stack *s); // d´epile et renvoie la valeur du sommet de s void push(Element e, Stack *s); // empile e au sommet de s
void freeStack(Stack *s); // lib´ere l’espace utilis´e par la pile s void emptyStack(Stack *s); // vide la pile s
Utiliser une pile pour calculer
int postValue(char *s){ // s: expression arith. postfix´ee 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 caract`ere }
i++;
}
return pop(&S);
}
Struct 17/21
D´ efinir 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 rat´ee!");
res.nb_elem=0;
return res;
}
Struct 18/21
Listes Listes chaˆın´ees en C Piles
D´ efinir 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){ /* acc´eder au sommet sans le d´epiler */
if(isEmptyStack(s))
error("pas de 1er ´el´ement 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];
}
Listes Listes chaˆın´ees en C Piles
D´ efinir 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;
}
en TP
Comment faire des piles avec des listes ? Quel est l’int´erˆet ?
Calculer des expressions arithm´etiques parenthes´ees.
Et pour faire une file ?
Struct 21/21