Les Fils Et Les Piles OAII
Les Fils Et Les Piles OAII
Les Fils Et Les Piles OAII
Les piles et les files que nous allons découvrir ici sont deux variantes un peu particulières des
listes chaînées. Elles permettent de contrôler la manière dont sont ajoutés les nouveaux
éléments. Cette fois, on ne va plus insérer de nouveaux éléments au milieu de la liste mais
seulement au début ou à la fin.
Les piles et les files sont très utiles pour des programmes qui doivent traiter des données qui
arrivent au fur et à mesure.
Les piles et les files sont très similaires, mais révèlent néanmoins une subtile différence que
vous allez rapidement reconnaître. Nous allons dans un premier temps découvrir les piles qui
sont similaires aux listes chaînées, à quelques mots de vocabulaire près.
1 - Les piles
Imaginez une pile de pièces (fig. suivante). Vous pouvez ajouter des pièces une à une en haut
de la pile, mais aussi en enlever depuis le haut de la pile. Il est en revanche impossible d'enlever
une pièce depuis le bas de la pile.
Le principe des piles en programmation est de stocker des données au fur et à mesure les unes
au-dessus des autres pour pouvoir les récupérer plus tard. Par exemple, imaginons une pile de
nombres entiers de type int (fig. suivante). Si on ajoute un élément (on parle d'empilage), il
sera placé au-dessus (fig. suivante).
Le plus intéressant est sans conteste l'opération qui consiste à extraire les nombres de la pile.
On parle de dépilage. On récupère les données une à une, en commençant par la dernière qui
vient d'être posée tout en haut de la pile (fig. suivante). On enlève les données au fur et à mesure,
jusqu'à la dernière tout en bas de la pile.
On dit que c'est un algorithme LIFO, ce qui signifie « Last In First Out ». Traduction : « Le
dernier élément qui a été ajouté est le premier à sortir ».
Les éléments de la pile sont reliés entre eux à la manière d'une liste chaînée. Ils possèdent un
pointeur vers l'élément suivant et ne sont donc pas forcément placés côte à côte en mémoire.
Le dernier élément (tout en bas de la pile) doit pointer vers NULL pour indiquer qu'on a touché
le fond (fig. suivante).
Il y a des programmes où vous avez besoin de stocker des données temporairement pour les
ressortir dans un ordre précis : le dernier élément que vous avez stocké doit être le premier à
ressortir.
Pour vous donner un exemple concret, votre système d'exploitation utilise ce type d'algorithme
pour retenir l'ordre dans lequel les fonctions ont été appelées. Imaginez un exemple :
Pour « retenir » l'ordre dans lequel les fonctions ont été appelées, votre ordinateur crée une pile
de ces fonctions au fur et à mesure (fig. suivante).
Voilà un exemple concret d'utilisation des piles. Grâce à cette technique, votre ordinateur sait
à quelle fonction il doit retourner. Il peut empiler 100 fonctions d'affilée s'il le faut, il retrouvera
toujours le main en bas !
Comme pour les listes chaînées, il n'existe pas de système de pile intégré au langage C. Il faut
donc le créer.
Chaque élément de la pile aura une structure identique à celle d'une liste chaînée :
La structure de contrôle contiendra l'adresse du premier élément de la pile, celui qui se trouve
tout en haut :
Vous noterez que, contrairement aux listes chaînées, on ne parle pas d'ajout ni de suppression.
On parle d'empilage et de dépilage car ces opérations sont limitées à un élément précis,
comme on l'a vu. Ainsi, on ne peut ajouter et retirer un élément qu'en haut de la pile.
On pourra aussi écrire une fonction d'affichage de la pile, pratique pour vérifier si notre
programme se comporte correctement.
1.3 - Empilage
Notre fonction empiler doit prendre en paramètre la structure de contrôle de la pile (de
type Pile) ainsi que le nouveau nombre à stocker.
Nous stockons ici des int, mais rien ne vous empêche d'adapter ces exemples avec un autre
type de données. On peut stocker n'importe quel type de données : des double, des char,
des chaînes, des tableaux ou même d'autres structures.
nouveau->nombre = nvNombre;
nouveau->suivant = pile->premier;
pile->premier = nouveau;
}
L'ajout se fait en début de pile car, comme on l'a vu, il est impossible de le faire au milieu d'une
pile. C'est le principe même de son fonctionnement, on ajoute toujours par le haut.
De ce fait, contrairement aux listes chaînées, on ne doit pas créer de fonction pour insérer un
élément au milieu de la pile. Seule la fonction empiler permet d'ajouter un élément.
1.4 - Dépilage
Le rôle de la fonction de dépilage est de supprimer l'élément tout en haut de la pile. Mais elle
doit aussi retourner l'élément qu'elle dépile, c'est-à-dire dans notre cas le nombre qui était stocké
en haut de la pile.
C'est comme cela que l'on accède aux éléments d'une pile : en les enlevant un à un. On ne
parcourt pas la pile pour aller y chercher le second ou le troisième élément. On demande
toujours à récupérer le premier.
Notre fonction depiler va donc retourner un int correspondant au nombre qui se trouvait
en tête de pile :
int nombreDepile = 0;
Element *elementDepile = pile->premier;
nombreDepile = elementDepile->nombre;
pile->premier = elementDepile->suivant;
free(elementDepile);
}
return nombreDepile;
}
Bien que cette fonction ne soit pas indispensable (les fonctions empiler et depiler
suffisent à gérer une pile ), elle va nous être utile pour tester le fonctionnement de notre pile et
surtout pour « visualiser » le résultat.
printf("\n");
}
int main()
{
Pile *maPile = initialiser();
empiler(maPile, 4);
empiler(maPile, 8);
empiler(maPile, 15);
empiler(maPile, 16);
empiler(maPile, 23);
empiler(maPile, 42);
return 0;
On affiche l'état de la pile après plusieurs empilages et une autre fois après quelques
dépilages. On affiche aussi le nombre qui est dépilé à chaque fois que l'on dépile. Le résultat
dans la console est le suivant :
Etat de la pile :
42
23
16
15
8
4
Je depile 42
Je depile 23
Etat de la pile :
16
15
8
4
2 - Les files
Les files ressemblent assez aux piles, si ce n'est qu'elles fonctionnent dans le sens inverse !
Dans ce système, les éléments s'entassent les uns à la suite des autres. Le premier qu'on fait
sortir de la file est le premier à être arrivé. On parle ici d'algorithme FIFO (First In First Out),
c'est-à-dire « Le premier qui arrive est le premier à sortir ».
Il est facile de faire le parallèle avec la vie courante. Quand vous allez pour le paiement d’une
facture d’eau ou d’électricité, vous faites la queue au guichet (fig. suivante).
En programmation, les files sont utiles pour mettre en attente des informations dans l'ordre dans
lequel elles sont arrivées. Par exemple, dans un logiciel de chat (type messagerie instantanée),
si vous recevez trois messages à peu de temps d'intervalle, vous les enfilez les uns à la suite des
autres en mémoire. Vous vous occupez alors du premier message arrivé pour l'afficher à l'écran,
puis vous passez au second, et ainsi de suite.
En C, une file est une liste chaînée où chaque élément pointe vers le suivant, tout comme les
piles. Le dernier élément de la file pointe vers NULL (fig. suivante).
Le système de file va ressembler à peu de choses près aux piles. Il y a seulement quelques
petites subtilités étant donné que les éléments sortent de la file dans un autre sens.
Nous allons créer une structure Element et une structure de contrôle File :
Comme pour les piles, chaque élément de la file sera de type Element. À l'aide du pointeur
premier, nous disposerons toujours du premier élément et nous pourrons remonter jusqu'au
dernier.
2.3 - Enfilage
La fonction qui ajoute un élément à la file est appelée fonction « d'enfilage ». Il y a deux cas à
gérer :
• soit la file est vide, dans ce cas on doit juste créer la file en faisant pointer premier
vers le nouvel élément créé ;
• soit la file n'est pas vide, dans ce cas il faut parcourir toute la file en partant du premier
élément jusqu'à arriver au dernier. On rajoutera notre nouvel élément après le dernier.
nouveau->nombre = nvNombre;
nouveau->suivant = NULL;
Vous voyez dans ce code le traitement des deux cas possibles, chacun devant être géré à part.
La différence par rapport aux piles, qui rajoute une petite touche de difficulté, est qu'il faut se
placer à la fin de la file pour ajouter le nouvel élément. Mais bon, un petit while et le tour
est joué.
2.4 - Défilage
Le défilage ressemble au dépilage. Étant donné qu'on possède un pointeur vers le premier
élément de la file, il nous suffit de l'enlever et de renvoyer sa valeur.
int nombreDefile = 0;
nombreDefile = elementDefile->nombre;
file->premier = elementDefile->suivant;
free(elementDefile);
}
return nombreDefile;
}
Exercice
Ecrire une fonction afficherFile, comme fait pour les piles.
Réalisez ensuite un main pour exécuter le programme. Vous devriez pouvoir obtenir un
rendu similaire à ceci :
Etat de la file :
4 8 15 16 23 42
Je defile 4
Je defile 8
Etat de la file :
15 16 23 42
Source : www.openclassrooms.com