• Aucun résultat trouvé

Types abstraits

N/A
N/A
Protected

Academic year: 2022

Partager "Types abstraits"

Copied!
6
0
0

Texte intégral

(1)

Conception de structures de donn´ ees

Cours 3 Types abstraits suivis de R´ecursion

11 mars 2013

Struct 1/24

Types abstraits

Struct 2/24

Types abstraits Implantation et utilisation ecursivit´e

D´ efinition

Un type abstrait est la sp´ecification d’un ensemble de donn´ees et de l’ensemble des op´erations qu’elles peuvent effectuer.

On dit qu’un tel type est abstrait parce qu’il est uniquement d´efinit par le cahier des charges qu’une structure de donn´ees doit ensuite impl´ementer.

B Pour utiliser un type abstrait, on ne doit absolument pas se servir de la fa¸ con dont il est impl´ ement´ e (on n’a d’ailleurs pas besoin de le savoir).

Exemples :

types Date et Heure et les fonctions pour les manipuler, type Ensemble (en TP),

types Polynˆome ou Matrice et leurs op´erations alg´ebriques, listes, piles, files, arbres binaires, ...

Struct 3/24

Types abstraits Implantation et utilisation ecursivit´e

Op´ erations sur les types abstraits

Les op´erations sont divis´ees en plusieurs types :

les constructeurs : ils permettent de cr´eer un nouvel

“objet” du type que l’on est en train de d´efinir. Il peut y avoir plusieurs constructeurs :

nouvel objet neutre ou vide, nouvel objet param´etr´e, nouvel objet al´eatoire, ...

les modificateurs : ils permettent de modifier les objets et leur contenu.

les observateurs : ils donnent des informations sur l’´etat de l’objet (valeurs, affichages, ...)

On ne manipule un type abstrait qu’avec les fonctions qui lui sont associ´ ees ! !

Struct 4/24

(2)

Types abstraits Implantation et utilisation ecursivit´e

Exemple du type Color

Fichier color.h :

typedef ... Color;

Color randomColor(void);

Color newColorRGB(int r, int g, int b);

void printRGB(Color c);

void printHexa(Color c);

Color grayScale(Color c);

Color mixColors(Color c1, Color c2);

void inverseColor(Color *c);

Programme principal :

#include "color.h"

int main (int argc, char *argv[]){

Color c1 = randomColor();

Color c2 = newColorRGB(255,0,0);

Color c3;

printRGB(c1);

printRGB(grayScale(c1));

printHexa(c2);

c3=mixColors(c1,c2);

printRGB(c3);

inverseColor(&c3);

printRGB(c3);

}

Struct 5/24

Types abstraits Implantation et utilisation ecursivit´e

Implantation et utilisation de types abstraits :

types structur´ es

Struct 6/24

Types abstraits Implantation et utilisation ecursivit´e

Struct

Les types structur´es sont un moyen privil´egi´e de d´efinir des types abstraits : ce sont des types complexes construits `a partir de types “plus simples” :

struct nomStructure { type champ1 nomChamp1;

type champ2 nomChamp2;

...

} ;

typedef nomStructure nomType ;

typedef struct {

type champ1 nomChamp1;

type champ2 nomChamp2;

...

} nomType ;

Si on d´efinit un pointeur sur une structure, la notation -> est un raccourci pour acc´eder aux champs :

typedef struct { double Re;

double Im;

} Complex;

Complex *c = &(Complex) { 0.3,1.2 } ; printf("%f+i*%fc", c->Re, c->Im);

Complex conjug = { c->Re,-c->Im } ;

Types abstraits Implantation et utilisation ecursivit´e

Le type Color - 1` ere version color.c

typedef struct { int hexa; }Color;

Color randomColor(void){

return (Color){myRand(0xffffff+1)};

}

Color newColorRGB(int r, int g, int b){

return (Color){(r<<16)+(g<<8)+b};

}

void printRGB(Color c){

printf("[%d,%d,%d] ",c.hexa>>16, (c.hexa & 0x00ff00)>>8 , (c.hexa & 0x0000ff));

}

void printHexa(Color c){

printf("#%x ", c.hexa);

}

Color grayScale(Color c){

int s=((c.hexa>>16) + ((c.hexa & 0x00ff00)>>8) + (c.hexa & 0x0000ff))/3;

Color res = {(s<<16)+(s<<8)+s};

return res;

}

Color mixColors(Color c1, Color c2){

return (Color){(c1.hexa+c2.hexa)/2};

}

void inverseColor(Color *c){

c->hexa=0xffffff-c->hexa;

}

(3)

Le type Color - 2` eme version color.c

typedef struct {

int red; int green; int blue;

}Color;

Color randomColor(void){

Color c={myRand(256), myRand(256), myRand(256)};

return c;

}

Color newColorRGB(int r, int g, int b){

Color c={r,g,b};

return c;

}

void printRGB(Color c){

printf("[%d,%d,%d] ",c.red, c.green, c.blue);

}

void printHexa(Color c){

printf("\#%x ", (c.red<<16) + (c.green<<8) + c.blue);

}

Color grayScale(Color c){

int s;

s=(c.red+c.blue+c.green)/3;

Color res = {s,s,s};

return res;

}

Color mixColors(Color c1, Color c2){

Color res;

res.red=(c1.red+c2.red)/2;

res.green=(c1.green+c2.green)/2;

res.blue=(c1.blue+c2.blue)/2;

return res;

}

void inverseColor(Color *c){

c->red=255-c->red;

c->green=255-c->green;

c->blue=255-c->blue;

}

Le programme principal (main) reste inchang´e... l’int´erˆet d’un type abstrait est que l’on peut l’utiliser, quelle que soit son impl´ementation, sans modifier les programmes qui y font appel.

Struct 9/24

Exemple du type SArray (tableaux tri´ es)

typedef ... SArray;

SArray newEmptySArray(void);

void printSArray(SArray t);

int getLength(SArray t);

int isEmpty(SArray t);

int isFull(SArray t);

int get(int i, SArray t);

int searchPosition(int elem, SArray t);

int search(int elem, SArray t);

void insertPosition(int elem, SArray *t, int i);

void delete(int i, SArray *t);

/***********************************************************/

void insert(int elem, SArray *t){

insertPosition(elem, t, searchPosition(elem,*t));

}

void randomSArray(int nb, SArray *t, int up){

int i;

for(i=0;i<nb;i++) insert(myRand(up),t);

}

Struct 10/24

Types abstraits Implantation et utilisation ecursivit´e

Exemple du type SArray - suite

int main (int argc, char *argv[]){

SArray t = newEmptySArray();

int i,j, up=20, taille=100;

srandom(time(NULL));

printSArray(t);

printf("t vide? %d, t plein? %d\n",isEmpty(t),isFull(t));

randomSArray(taille, &t, up);

printf("t vide? %d, t plein? %d\n",isEmpty(t),isFull(t));

printSArray(t);

printf("indice de %d dans t: %d\n", 1, search(1,t));

for(i=0;i<up;i++){

j=search(i,t);

printf("verification: get(search(%d,t),t): %d\n", i,j==-1?-1:get(j,t) );

}

while( (i=search(5, t)) != -1 ) delete(i, &t);

printf("longueur de t: %d\n", getLength(t));

printSArray(t);

}

Struct 11/24

Types abstraits Implantation et utilisation ecursivit´e

Exemple du type SArray - fin

typedef struct{ int lg; int tab[MAX SIZE]; }SArray;

SArray newEmptySArray(void){ SArray res;

res.lg=0;

return res;

}

void printSArray(SArray t){

printTab(t.tab, t.lg);

}

int getLength(SArray t){

return t.lg;

}

int isEmpty(SArray t){

return (t.lg==0);

}

int isFull(SArray t){

return (t.lg==MAX_SIZE);

}

int get(int i, SArray t){

if (i<0 || i>=t.lg)

erreur("L’indice %d est incorrect!", i);

return t.tab[i];

}

void insertPosition(int elem, SArray *t, int i){

...

}

void delete(int i, SArray *t){

...

}

int searchPosition(int e, SArray t){

return isEmpty(t)?0:searchPos(e,t.tab,0,t.lg-1);

}

int search(int elem, SArray t){

return dichoSearch(elem, t.tab, 0, t.lg-1);

}

Struct 12/24

(4)

Types abstraits Implantation et utilisation ecursivit´e

Exemple du type SArray - 2e fin

Ou alors...

typedef struct { int lg; int *tab; } SArray;

SArray newEmptySArray(void) { SArray res;

res.lg=0;

if( (res.tab=malloc(MAX SIZE*sizeof(int))) == NULL ) erreur("Allocation rat´ ee!");

return res;

} ...

Struct 13/24

Types abstraits Implantation et utilisation ecursivit´e

Un peu de r´ ecursivit´ e

Struct 14/24

Types abstraits Implantation et utilisation ecursivit´e

Structures r´ ecursives

Il est possible de cr´eer des structures de donn´ees r´ecursives, c’est-`a-dire qu’elles sont d´efinies en fonction d’elles-mˆemes (c’est le cas des listes, des arbres, ...).

! Il faut faire attention en d´efinissant de tels types : typedef struct {

int toto;

TR next;

} TR; /* FAUX ! */

typedef struct structRec { int toto;

struct structRec *next;

} TR; /* OK ! */

On ne peut pas d´efinir un type en fonction de lui-mˆeme ; Il faut que l’on puisse d´eterminer l’espace m´emoire

n´ecessaire `a la structure.

Rmq : les fonctions r´ecursives sont particuli`erement adapt´ees lorsque les structures qu’elles manipulent sont r´ecursives.

Types abstraits Implantation et utilisation ecursivit´e

Exemple du type Person

typedef struct person{

char *firstName; /* pr´enom */

char *lastName; /* nom */

struct person *father;

struct person *mother;

}Person;

Person *createPerson(char *f, char *l){

Person *h;

if ((h=malloc(sizeof(Person)))==NULL) error("Allocation rat´ee!");

h->firstName=f; h->lastName=l; h->father=NULL; h->mother=NULL;

return h;

}

Person *createPersonWithParents(char *f, char *l, Person *dad, Person *mum){

Person *h=createPerson(f,l);

h->father=dad; h->mother=mum;

return h;

}

Person *createPersonWithParentsNames(char *f, char *l, char *dad, char *mum){

Person *d=createPerson(dad,"");

Person *m=createPerson(mum,"");

return createPersonWithParents(f,l,d,m);

}

(5)

Types abstraits Implantation et utilisation ecursivit´e

Exemple du type Person - suite

void printName(Person *h){

printf("%s %s", h->firstName, h->lastName);

}

void printPerson(Person *h){

printf("%s %s ( p`ere: ", h->firstName, h->lastName);

(h->father==NULL)?printf("x"):printName(h->father);

printf("; m`ere: ");

(h->mother==NULL)?printf("x"):printName(h->mother);

printf(") ");

}

int main (int argc, char *argv[]){

Person *a = createPerson("Anabelle", "Curie");

printName(a); printf("\n");

Person *b = createPerson("Bernard", "Plank");

printName(b); printf("\n");

Person *c = createPersonWithParents("Clothilde", "Plank", b, a);

printPerson(c); printf("\n");

Person *d = createPersonWithParentsNames("Dany", "Newton", "Flint", "Fiona");

printPerson(d); printf("\n");

}

Struct 17/24

Types abstraits Implantation et utilisation ecursivit´e

Fonctions r´ ecursives

Struct 18/24

Types abstraits Implantation et utilisation ecursivit´e

Qu’est-ce qu’une fonction r´ ecursive ?

Une fonction qui s’appelle elle mˆeme... par exemple : void toto(int i) {

printf("%d ",i);

toto(i);

}

Il faut toujours s’assurer que la fonction termine ! void toto(int i) {

if(i>0) {

printf("%d ",i); toto(i-1);

} }

Pour r´esoudre le probl`eme P : si le probl`eme est suffisamment petit, on le r´esout directement, sinon on r´esout r´ecursivement un probl`eme plus petit pour arriver ` a la solution de P.

Struct 19/24

Types abstraits Implantation et utilisation ecursivit´e

Structure d’une fonction r´ ecursive

Comment ´ecrire la fonction r´ecursive int sumRec(int param) pour calculer la somme des entiers de 1 `a param ?

Il faut TOUJOURS un cas d’arrˆet : dans quel cas (pour quelle valeur de param) sait on r´esoudre le probl`eme directement ?

B if( n == 1 ) return 1;

Pour r´esoudre r´ecursivement, l’id´ee c’est d’imaginer que la fonction que l’on est en train d´ecrire existe d´ej` a et qu’on peut l’utiliser, `a condition que le param`etre soit ”plus petit” que param.

B int s = sumRec( param - 1 );

On utilise alors cette solution r´ecursive pour r´esoudre le probl`eme principal (de param`etre param).

B return param + s;

Struct 20/24

(6)

Types abstraits Implantation et utilisation ecursivit´e

Exemples de fonctions r´ ecursives

int sumRec(int param){ // somme des entiers de 1 ` a param if( param == 1 )

return 1;

else{

int s = sumRec( param - 1 );

return param + s;

} }

void printTab(int *tab, int lg){ // affiche un tab. d’entiers if ( lg == 1 )

printf("%d\n",tab[0]);

else{

printf("%d ",tab[0]);

printTab(tab+1, lg-1); // et si on inverse?

} }

Struct 21/24

Types abstraits Implantation et utilisation ecursivit´e

R´ ecursif vs. it´ eratif

Toutes les fonctions r´ecursives peuvent s’´ecrire de fa¸con it´erative et inversement :

int sumRec(int param){ // somme des entiers de 1 ` a param if( param == 1 )

return 1;

else{

int s = sumRec( param - 1 );

return param + s;

} }

int sumIte(int param){ // somme des entiers de 1 ` a param int i, s=0;

for( i=1; i<=param; i++) s+=i;

return s;

}

Struct 22/24

Types abstraits Implantation et utilisation ecursivit´e

R´ ecursif vs. it´ eratif nombres de Fibonacci

int fibo(int n){

int i, tmp, f1=1, f2=1;

for(i=3; i<=n; i++){

tmp=f2;

f2=tmp+f1;

f1=tmp;

}

return f2;

}

int fiboRec(int n){

if(n<=2) return 1;

else return fiboRec(n-1)+fiboRec(n-2);

}

Types abstraits Implantation et utilisation ecursivit´e

Fonctions r´ ecursives sur le type Person

void printMothers(Person *p){

if (p->mother!=NULL){

printName(p->mother);

printf("\n");

printMothers(p->mother);

} }

void printAncestors(Person *p){

if (p->mother!=NULL){

printName(p->father); printf("\n");

printName(p->mother); printf("\n");

printAncestors(p->father);

printAncestors(p->mother);

}

}

Références

Documents relatifs

C'est une instance qui se réunit à titre exceptionnel, sur décision du chef d'établissement, lorsque le comportement et l'attitude d'un ou plusieurs élèves sont dangereux pour

[r]

Universit´ e Pierre et Marie Curie – Paris 6 Examen de rattrapage Licence de Math´ ematiques Analyse Hilbertienne et Num´ erique.. 29 janvier 2007 9h

Ecrire une fonction Pachinko1 sans argument et en utilisant une boucle for qui simule la descente d'une bille et renvoie le numero du trou dans lequel elle est tombée..4. Ecrire

Le syst` eme admet un d´ eterminant diff´ erent de 0 (il vaut − 34), il admet donc une unique solution qui est la solution nulle (et on n’a pas besoin des formules de Cramer

Soit F un sous espace vectoriel ferm´ e d’un espace de Hilbert muni d’un produit scalaire h., .i et d’une

Cette ´ equation signifie que pour que la convection transporte de la chaleur il faut que les variation lat´ erales de v z et de δT soient corr´ el´ ees et, pour le flux soit vers

´ Ecrire une fonction nombreDeUns d’argument un entier naturel n, qui renvoie le nombre de chiffres de 1 dans l’´ ecriture binaire de n.. Soit n un