name: inverse layout: true class: center, middle, inverse --- # INFORMATIQUE 3 - CM2 ## Inès de Courchelle ## 2024-2025  --- layout: false # Let's go ## Objectifs - Étudier des structures de données - Connaître les fonctionnalités d'une pile et d'une file - Appréhender des notions de gestion de données
--- # À quoi ça sert ? ## Définition - C’est une structure de données et une organisation logique des données afin de simplifier et/ou d’accélerer un traitement - FIFO (**F**irst **I**n et **F**irst Out) et LIFO (**L**ast **I**n et **F**irst **O**ut) sont des paradigmes utilisés dans d’autres domaines de l’informatique tel que : - Réseau (demande de ressource) - Microprocesseur (en pile) - Algorithme d’intelligence artifielle ...
--- # Les Piles ## Définitions - Stack en anglais - Souvent utilisé pour stocker les valeurs des variables locales et dans le stockage de données - LIFO (**L**ast **I**n **F**irst **O**ut) : Les derniers éléments ajoutés à la Pile sont recupérés en premier. - Le principe des piles en programmation est de stocker des données au fur et à mesure les unes au dessus des autres. .pull-left[
] .pull-right[
] --- # Les Piles ## Représentation .pull-left[
] .pull-right[ #### Remarques : - La pile est un pointeur qui pointe vers le premier élément - Le deuxième élément pointe vers le troisième élément, ... - Les données de la pile peuvent être de n’importe quel type : entier, réel, caractères, tableau ... - Dans une pile, les éléments sont tous de même type (et on peut choisir le type qu'on veut : entier, réel, chaine, structure ...) ] --- # Les Piles ## Comment la représenter en algo ? Via une structure ## Quelles informations ? - Une donnée - L'adresse de l'élément suivant ## Exemple
--- # Les structures (Rappel) ## Définition du type structuré ```c STRUCTURE nomType nomChamp1 : TYPE1, nomChamp2 : TYPE2, ...., nomChampn : TYPEn FIN STRUCTURE ``` ## Déclaration de variable ```c elt1, elt2 : nomType ``` ## Manipulation Accéder au champ nomChampN°i de la variable elt1 se fait selon : elt1.nomChampi --- # Les structures (Rappel) ## Exemple
--- # Les structures (Rappel) ## Exemple .pull-left[
] .pull-right[ ```c STRUCTURE etudiant nom : chaine de caractères, prénom : chaine de caractères, numeroEtudiant : entier, niveau : chaine de caractères, age : entier FIN STRUCTURE ``` ] --- # Les structures (Rappel) ## Constructeur Constructeur de variable de type structuré (permet de valider les préconditions sur le type et de retourner la variable ou bien de planter le programme) ## Exemple ```c FONCTION creerType(val1 : TYPE1, val2 : TYPE2, ...) : nomType VARIABLES res : nomType DÉBUT SI (problème(val1, val2, ...)) ALORS écrire (“Un message d’erreur explicite”) erreur() // met fin au programme en erreur FIN SI res.nomChamp1 <- val1 res.nomChamp2 <- val2 retourner res FIN ``` --- # Les piles - en ALGO ## Définition du type structuré ```c STRUCTURE ElementP 'type' donnee ElementP suivant FIN STRUCTURE ``` ## EN gros
--- # Les Piles - Concrétement en C ## Dans un Pile.h on va définir notre structure ```c typedef struct{ int donnee; struct ElementP* suivant; }ElementP; typedef ElementP* Pile; ``` ## Dans le main on va initialiser notre structure ```c int main(){ Pile p=NULL ; /* elle ne pointe sur rien à l’état initial */ return 0; } ``` --- # Les Piles ## Concrétement en C .pull-left[ #### Le code en C ```c typedef struct ElementP{ int donnee; struct ElementP* suivant; }ElementP; typedef ElementP* Pile; ``` ] .pull-right[ #### Illustration
]
- Notre variable p pointe vers le premier élément de la pile - Le premier élément est constitué d'une donnée et de l'adresse de l'élément suivant --- # (Rappel) ## Les Structures - On sort des piles et des files et on va parler un peu des structures - Et plus particulièrement, lorsqu'on utilise des pointeurs + des structures
--- # (Rappel) ## Pointeurs et Structures .pull-left[ #### Nous considérons la structure suivante : ```c typedef struct { int x; int y; }coordonnee; ``` .underV[Ici, j'ai déclaré une structure]
] .pull-right[ #### Dans mon utilisation en C ```c coordonnee c1; coordonnee c2; c1.x=4; c1.y=4; c2.x=5; c2.y=3; ``` .underV[Ici, j'ai déclaré des coordonnées :]
]
.underR[Mais que se passe t-il si j'utilise des pointeurs ?] --- # (Rappel) ## Pointeurs et Structures .pull-left[ #### Nous considérons TOUJOURS la structure suivante ```c typedef struct { int* x; int* y; }coordonnee; ```
] .pull-right[ #### Dans mon utilisation en c ```c coordonnee c1; coordonnee c2; c1->x=4; c1->y=4; c2->x=5; c2->y=3; ```
]
- On demande à c1 d'aller vers la valeur vers laquelle pointe y - On demande à c1 d'aller vers la valeur vers laquelle pointe x --- # Let's Go ## Revenons à nos moutons !!
--- # Les Piles ## Les fonctions de base #### En Algo ```c Fonction creerPileVide() : Pile Fonction creerElementPile(e : ElementP) : ElementP Fonction estPileVide(p : Pile) : booleen Procédure empiler(p : Pile, e : ElementP) Fonction depiler(p : Pile) : ElementP Procédure viderPile(p : Pile) Procédure afficherPile(p : Pile) ``` #### En C ```c Pile creerPileVide(); ElementP creerElementPile(ElementP e); int estPileVide(Pile p); void empiler(Pile p, ElementP e); ElementP depiler(Pile p); void viderPile(Pile p); void afficherPile(Pile p); ``` --- # Les Piles - Empiler un élément ## Les Etapes : 1. Le nouvel élément arrive 2. Le pointeur de la pile arrête de pointer sur le premier élément 3. Le pointeur de la pile pointe sur le nouvel élément (en haut de la pile) et pointe vers l’ancien haut de la pile
--- # Les Piles - Empiler un élément
--- # Les Piles - Empiler un élément
--- # Les Piles - Empiler un élément
--- # Les Piles - Empiler un élément ## En c ```c PROCEDURE empiler(p : pile, valeur : entier) VARIABLES nvElt : ElementP DEBUT nvElt <- creerElementPile(valeur) SI (estVide(p) ALORS p <- nvElt SINON nvElt.suivant <- p p <- nvElt FIN SI FIN ```
--- # Les Piles - Empiler un élément ## Concrétement en C - Dans le main.c ```c int donnee=4; /* la valeur à empiler */ Pile p=NULL; /* Premier élément de la pile */ p=empiler(p,donnee); /* la pile et la donnee */ ```
--- # Les Piles - Dépiler un élément ## Etapes : 1. Le pointeur de la pile ne pointe plus vers le premier élément 2. Le pointeur de la pile pointe vers le deuxième élément 3. L’ancien élément est libéré (free)
--- # Les Piles - Dépiler un élément
--- # Les Piles - Dépiler un élément
--- # Les Piles - Dépiler un élément
--- # Les Piles - Dépiler un élément ## Attention à l'algo 1. Vérifier si la pile n'est pas vide 2. Mémoriser la valeur à dépiler 3. Mémoriser le second élément 4. Libérer l'espace utilisé par l'élément 5. Faire pointer la pile vers le second 6. Retourner la donnée à dépiler
--- # Les Piles - Dépiler un élément ## L'algo ```c FONCTION depiler(p : pile) : entier VARIABLE valeurDepile : entier avantDernier : ElementP DEBUT SI p=NULL alors exit(EXIT_FAILURE) SINON valeurDepile <- p.donnee avantDernier <- p.suivant p <- avantDernier FIN SI retourner valeurDepile FIN ``` --- # Les Piles - Dépiler un élément ## Concrétement en C - Dans le main.c ```c int donnee; /* la valeur à récupérer */ Pile p=NULL; /* premier élément de la pile */ p = empiler(p,4); p = empiler(p,5); /* on récupére la valeur du haut de la pile dans la variable donnée */ donnee=depiler(&p); printf("%d",donnee); ``` Quel sera la valeur affichée ? --- # Les piles - Vider la pile ## Principe Utiliser la fonction dépiler tant que la pile n’est pas vide
--- # Les Piles - Vider la pile ## Algo .pull-left-small[
] .pull-right-big[ ```c PROCEDURE viderP(p : pile) VARIABLES valeurDepiler: entier DEBUT /* tant que la pile n'est pas vide : !estvide(p) */ TANT QUE (!estVide(p)) FAIRE valeurDepiler <-depiler(p) FIN TANT QUE FIN ``` ] --- # Les Piles - Vider la pile ## ALGO
--- # Les Piles - Vider la pile ## ALGO - en récursif ! ```c PROCEDURE viderPile(p : pile): pile DEBUT SI (!estvide(p)) alors depiler(p) p <- viderPile(p.suivant) FIN SI FIN ``` --- # Les Piles - Inverser ## Pourquoi ? - je ne sais pas, Parce que ! - En Vrai, pour faire une deuxième pile ## Comment ? - ... - Un appel récursif !
--- # Les Piles - Inverser Nous allons dépiler le contenu de notre pile et nous allons l'empiler dans une autre.
--- # Les Piles - Inverser Nous allons dépiler le contenu de notre pile et nous allons l'empiler dans une autre.
--- # Les Piles - Inverser Nous allons dépiler le contenu de notre pile et nous allons l'empiler dans une autre.
--- # Les Piles - Inverser Nous allons dépiler le contenu de notre pile et nous allons l'empiler dans une autre.
--- # Les Piles - Inverser ## L'algo ```c FONCTION inverserP(p1,p2 : pile) : pile VARIABLE elt : entier DEBUT SI (estvide(p)) alors retourner (p2) SINON elt <- depiler(p1) p2 <- empiler(p2,elt) retourner inverserP(p1,p2) FIN SI FIN ``` --- # Les Piles - Inverser ## Dans mon utilisation en c ```c Pile p1=NULL; Pile p2=NULL; empiler(&p1,3); empiler(&p1,2); empiler(&p1,1); p1=inverserP(&p1,&p2); ``` #### C'est pas BEAU ! --- # Les Piles - Inverser ## C'est pas beau ```c Pile p1=NULL; Pile p2=NULL; empiler(&p1,3); empiler(&p1,2); empiler(&p1,1); p1=inverserP(&p1,&p2); ``` ## Mais est ce bien terminé ? - NAN - Il nous faut une fonction tampon ! --- # Les Piles - Inverser ## C'est Beau ! ```c Pile inverserP(Pile p1){ Pile p2= NULL; p2= inverserPCache(&p1,&p2); return p2; } ``` #### Mais que dois-je déclarer dans mon .h ? --- # Les Piles - Inverser ## VAR
Cette vidéo ne peut être affichée sur votre navigateur Internet.
Une version est disponible en téléchargement sous
adresse du lien
.
--- # Les Piles - Afficher ## ATTENTION Il faut utiliser un pointeur de pile ## Mais Pourquoi ? Sinon nous allons perdre le sommet de notre pile
--- # Les Piles - Afficher ## Illustration
--- # Les Piles - Afficher ## Illustration
--- # Les Piles - Afficher ## Illustration
--- # Les Piles - Afficher ## Illustration
--- # Les Piles - Afficher ## Illustration
--- # Les Piles - Afficher ## Algo ```c PROCEDURE afficherP(p : pile) VARIABLE temp : pile DEBUT SI (!estVide(p)) temp <- p; TANT QUE (!estVide(temp)) FAIRE ECRIRE("il y a" + temp.donnee) temp <- temp.suivant FIN TANT QUE SINON ECRIRE("Il n'y a rien dans ta pile") FIN SI FIN ``` --- # Les Piles - Afficher ## Dans mon utilisation en c ```c Pile p = NULL; p = empiler(p,394); p = empiler(p,33); p = empiler(p,42); afficherP(p); ```
--- # Les Piles - Afficher en Récursif ## Mais pourquoi ? - Parce que vous êtes grand ! - Et que la récursivité n'a plus de secret pour vous !
--- # Les Piles - Afficher en Récursif ## Rappel 1. La condition d'arrêt 2. La résolution du problème 3. L'appel récursif
--- # Les Piles - Afficher en Récursif ## 1. La condition d'arrêt Je suis à la fin de la liste ## 2. La résolution du problème J'affiche l'élément courant ## 3. L'appel récursif Je passe la pile avec l'élément suivant --- # Les Piles - Afficher en Récursif ## L'algo ```c PROCEDURE afficherP(p : Pile) DEBUT SI (estVide(p)) alors ECRIRE("---") SINON ECRIRE("elt =>" + p.donnee) afficherP(p.suivant) FIN SI FIN ```
--- # Les Piles - Bilan ## Les fonctionnalités possibles .pull-left[ ```c Fonction creerPileVide() : Pile Fonction creerElementPile(e : ElementP) : ElementP Fonction estPileVide(p : Pile) : Entier Procédure empiler(p : Pile, e : ElementP) Fonction depiler(p : Pile) : ElementP Procédure viderPile(p : Pile) Procédure afficherPile(p : Pile) ``` ] .pull-right[
] --- # Les Files ## Définition - Queue en anglais - Souvent utilisé pour stocker les valeurs des variables locales et ans le stockage de données - FIFO (**F**irst **I**n **F**irst **O**ut) : Les premiers éléments ajoutés à la File sont recupérés en premier.
--- # Les Files ## La structure
--- # Les Files - Concrétement en C ## Dans un File.h on va définir notre structure ```c typedef struct ElementF{ int donnee; struct ElementF* precedent; }ElementF; typedef ElementF* File; ``` ## Dans la fonction main (main.c), on va initialiser notre structure ```c int main(){ File f=NULL ; /* elle ne pointe sur rien à l’état initial */ return 0; } ``` --- # Les Files ## Les fonctions de bases #### En Algo ```c Fonction creerFileVide() : File Fonction creerElementFile(e : ElementF) : ElementF Fonction estFileVide(f : File) : booleen Procédure enfiler(f : File, e : ElementF) Fonction defiler(f : File) : ElementF Procédure viderfile(f : File) Procédure afficherFile(f : File) ``` #### En C ```c Pile creerFileVide(); ElementF creerElementFile(ElementF f); int estPileVide(File f); void enfiler(File f, ElementF f); ElementF defiler(File f); void viderFile(File f); void afficherFile(File f); ``` --- # Les Files - Enfiler un elément ## Algo 1. Créer un nouvel élément 2. Si la liste est vide, le nouvel élément créé est le début 3. Sinon il faut parcourir toute la file jusqu'à la fin
--- # Les Files - Enfiler un élément ## Let's go 1. Création d'un nouvel élément vide 2. On ajoute l'élément à la fin, donc ce nouvel élément n'a pas de précédent 3. L'élément prend la valeur que l'on désire ajouter 4. Deux cas se présentent : - **cas 1** : - Si c'est la première fois que l'on ajoute un élément *c'est à dire, lorsque la file est vide* - Alors, notre file est égale au première élément - **cas 2** : - La file contient déjà des éléments - il faut donc parcourir l'ensemble de la file pour pouvoir rajouter l'élément à la fin de la file ! - il faut un pointeur temporaire et on parcours la file jusqu'à la fin --- # Les Files - Enfiler un élément
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Algo ```c PROCEDURE enfiler(f : file, valeur : entier) VARIABLES nvElt : element de file temp : une File DEBUT nvElt <- creerElementFile(valeur) nvElt.donnee <- valeur SI (estVide(f)) ALORS f<-nvElt SINON temp <- f TANT QUE (!estVide(temp.precedent)) FAIRE temp<-temp.precedent FIN TANT QUE temp.precedent<-nvElt FIN SI FIN ``` --- # Les Files - Enfiler un élément ## Attention
--- # Les Files - Enfiler un élément ## ALGO recursif ! ```c FONCTION enfiler(f : file, valeur : entier): file VARIABLE nvElt : Element de file DEBUT SI (estVide(f)) ALORS elt <- creerElementFile(valeur) f <- elt retourner f SINON f.precedent <- enfiler(f.precedent,valeur) retourner f FIN SI FIN ``` --- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Enfiler un élément ## Illustration
--- # Les Files - Défiler un élément ## ALGO 1. Vérifier si la file n'est pas vide 2. Enregistrer la valeur à défiler 3. Mémoriser l'adresse de l'élément précédent 4. Libérer la mémoire 5. Faire pointer la file vers l'ancien second de la file
--- # Les Files - Défiler un élément ## Illustration
--- # Les Files - Défiler un élément ## Illustration
--- # Les Files - Défiler un élément ## Illustration
--- # Les Files - Défiler un élément ## Illustration
--- # Les Files - Défiler un élément ## Illustration
--- # Les Files - Défiler un élément ## L'algo ```c FONCTION defiler(f: file) : entier VARIABLE valeurDefilee : entier temp : élément de file DEBUT SI (!estVide(f)) ALORS valeurDefilee <- f.donnee temp <- f.précedent f <- temp FIN SI retourner valeurDefilee FIN ``` --- # Les Files - Inverser ## Comment inverser une file avec des notions vues précédements ?
--- # Les Files - Inverser ## Illustration
--- # Les Files - Inverser ## Illustration
--- # Les Files - Inverser ## Illustration
--- # Les Files - Inverser ## Illustration
--- # Les Files - Inverser ## Illustration
--- # Les Files - Inverser ## Illustration
--- # Les Files - Inverser ## Illustration
--- # Les Files - Inverser ## Avec un appel récursif ```c FONCTION inverserF(f: file) : file VARIABLE elt: entier DEBUT SI (estVide(f)) ALORS returner f SINON elt <- defiler(f) f <- inverserF(f) enfiler(f,elt) retourner f FIN SI FIN ``` --- # Les Files - Inverser ## Avec un appel récursif
--- # Les Files - Afficher ## L'algo ```c PROCEDURE afficherF(f : file) DEBUT SI (f=NULL) alors ECRIRE("---") SINON printf("elt =>" + f.donnee) afficherF(f.precedent) FIN SI FIN ```
--- # Les Files - Bilan ## Ce qu'on peut faire ```c Fonction creerFileVide() : File Fonction creerElementFile(e : ElementF) : ElementF Fonction estFileVide(f : File) : booleen Procédure enfiler(f : File, e : ElementF) Fonction defiler(f : File) : ElementF Procédure viderfile(f : File) Procédure afficherFile(f : File) ``` ] .pull-right[
] --- # VERSION FINALE ## VAR
Cette vidéo ne peut être affichée sur votre navigateur Internet.
Une version est disponible en téléchargement sous
adresse du lien
.
--- # C'est l'heure du Bilan ## Avantage des piles/files par rapport au tableau ? - pas besoin de définir de taille de tableau - pas besoin de connaître la taille du tableau pour le parcourir - pas besoin de faire de #define N 10
#### Attention Une pile et une file ne servent pas à accéder à un élément n de notre structure !