Professional Documents
Culture Documents
Chapitre3 Partie 03
Chapitre3 Partie 03
Données
– Cours –
Chapitre 03 : Structures de données linéaires : Liste, Pile et
File
Partie03: Les Types Abstraits PILE et FILE et leurs implémentations
possibles
Staff pédagogique
Nom Grade Faculté/Institut Adresse e-mail
BELALA Faiza Professeur Nouvelles Technologies Faiza.belala@univ-constantine2.dz
HAMMOUD Djamila MCB Nouvelles Technologies Djamila.hammoud@univ-
constantine2.dz
Etudiants concernés
Faculté/Institut Département Année Spécialité
Nouvelles Technologies MI Licence 2
Objectifs du cours
Cette dernière partie du chapitre 03 permet d'une part, d'introduire les piles et les files comme étant
des structures de données particulières des listes. Leurs TAD sont présentés, ensuite des
Concrêtement une définition alternative peut être donnée pour la liste, on peut utiliser la définition
récursive suivante:
Une liste d’éléments est soit la liste vide, soit une paire (t, r) où t est le premier élément de
la liste et r est la liste restante.
Dans ce type de liste, équivalente à la liste itérative, on peut raisonner de façon récursif plus
naturellement. La notion de position des éléments n'est pas définie explicitement. Ceci rend la
manipulation de la liste à travers ses opérations plus simple.
Deux cas particuliers des listes (récursives) jouent un rôle important en informatique: les piles où
les données sont ajoutées et supprimées en une même extremité (sommet); les files, où les données
sont ajoutées à une extrémité de la liste (queue) et supprimées à l’autre extrémité (tête).
Une pile est une collection d’objets qui obeit au protocole LIFO (Last In First Out). Elle est utilisée
comme :
Une Pile de procédures appelées en cascade pour exécution.
Une Pile d’appels d’une procédure récursive.
Calcul des expressions arithmétiques.
Dans le cas de la structure file, on procède sur la base du ”premier arrivé premier servi”. Par
analogie avec les files d’attente réelles (guichets, trafic automobiles, etc), la liste linéaire récursive
dite file est une structure qui permet de stocker des objets dans un ordre donné et de les retirer dans
le même ordre, c’est à dire selon le protocole FIFO (”First In First Out”). On ajoute toujours un
élément en queue de liste et on retire celui qui est en tête de liste.
On peut donner aux éléments de la file des priorités différentes qui leur permettent de dépasser les
éléments moins prioritaires. De tels problèmes apparaissent dans:
Les réseaux de télécommunications
Demandes d’allocation de ressources dans les Systèmes d’Exploitation
Files d’attente des E/S
Les programmes de gestion du courrier électronique
Files des requêtes reçues par un serveur de BD (un serveur Web, un moteur de recherche)
Support du protocole ”producteur/consommateur” entre deux processus asynchrones. Un
processus produit des données, il faut passer par l’intermédiaire d’une file pour gérer
l’attente des données avant d’être consommer.
TAD Pile
Sorte pile
Utilise Booléen, Elément,Entier
Opérations:
Pile-vide: → pile
empiler: pile, élément → pile
dépiler: pile → pile
sommet: pile → élément
taille: pile → entier
est_vide: pile → booléen
Préconditions:
Pré(dépiler(p)) est définie ssi est_vide(p)=faux
Pré(sommet(p)) est définie ssi est_vide(p)=faux
Axiomes:
dépiler(empiler(p,e)) ≡ p
sommet(empiler(p,e))≡ e
taille (pile-vide) ≡ 0
taille (empiler(p,e)) ≡ 1+ taille (p)
est_vide(pile_vide) ≡ vrai
est_vide(empiler(p,e)) ≡ faux
Variables:
p:pile; e:élément
Les opérations internes sont dans ce cas, pile-vide, empiler (constructeurs) et dépiler (non
constructeur). Les opérations observateurs sont: sommet, taille et est_vide.
Nous pouvons enrichir le TAD pile par d’autres opérations analogues à celles des listes linéaires.
L’implémentation de ce TAD se fait aussi soit de manière chainée ou contigue, comme suit:
fin
Nous constatons que dans cette implémentation (chainée) de la pile, les opérations d'insertion et de
suppression d'éléments au début de la pile se font de manière très simple. C'est aussi le cas dans
l'implémentation contigue (ci dessous) à condition de considérer le sommet de la pile comme
dernier élément du tableau, c'est à dire, l'élément qui se trouve à l'indice dont la valeur est donnée
par le champs longueur de l'enregistrement Pile.
Début
P.Longueur =0
Retourner(P)
fin
Le seul problème qui peut se poser pour cette implémentation (contigue) de la pile réside dans la
limite imposée par la structure tableau, au delà de Lmax, on ne peut plus insérer des éléments dans
la pile.
Parmi les opérations internes sur les files, nous avons: ajouter un élément à la file, retirer le premier
élément de la file, et la création d’une file vide. Les opérations observateurs sont entre autre: tester
si une file est vide, accéder au premier et au dernier élément de la file et calculer sa longueur. Son
TAD est donné par ce qui suit:
TAD File
Sorte file
Utilise Booléen, Elément, Entier
Opérations:
file-vide: → file
enfiler: file, élément → file
défiler: file → file
tête, queue: file → élément
taille: file → entier
est_vide: file → booléen
Préconditions:
Pré(défiler(f)) est définie ssi est_vide(f) = faux
Pré(queue(f)) est définie ssi est_vide(f) = faux
Pré(tête(f)) est définie ssi est_vide(f) = faux
Axiomes:
Défiler(enfiler(f,e)) ≡ si est_vide(f) alors file_vide sinon
enfiler(défiler(f),e)
tête(enfiler(f,e))≡ si est_vide(f) alors e sinon tête(f)
queue(enfiler(f,e))≡ e
taille(f) ≡ si f=file-vide alors 0 sinon 1+taille(défiler(f))
est_vide(file_vide) ≡ vrai
est_vide(enfiler(f,e)) ≡ faux
Variables:
f: file; e: élément
La file est aussi une liste particulière, son implémentation peut aussi être faite de manière contigue
ou chainée.
Dans la représentation chaînée des files, le même principe pour l’implémentation des listes est
utilisé, seulement pour améliorer les opérations d’ajout dans une file, on utilise alors une structure
composée de deux entités:
1. ftête: qui est un pointeur vers une liste qui contient tous les éléments de la file.
2. fqueue: qui représente un pointeur vers le dernier élément de la file ou le pointeur
Null si la file est vide.
tête queue
….
info suiv
Déclaration
F: file
Début
F.ftête = Null
F.fqueue = Null
Retourner F
fin
enfiler: file, élément → file Fonction enfiler(D F: file, Donnée e:élément): file
Déclaration
Nouv: pointeur de cellule
Début
Nouv = allouer(cellule)
Nouv.info=e
Nouv.suiv=Null
Si F=file-vide() alors
F.ftête= Nouv
Sinon F.queue.suiv= Nouv
fsi
F.fqueue= Nouv
retourner(F)
Fin
défiler: file → file Fonction défiler( D F: File): File
Début
F.ftête= F.ftête.Suiv
Si F.ftête= = Null /* cas d’une file avec un seul élément */
Alors F.fqueue = Null
Fsi
retourner(F)
Fin
Tête : file→ élément Fonction tête ( D F:file): élément
Début
Retourner F.ftête.Info
Fin
Queue: file→ élément Fonction queue ( D F:file): élément
Début
Retourner F.fqueue.Info
Fin
Est-vide: file → bool Fonction est-vide ( D F:file): bool
Début
retourner (F==file-vide( ))
Fin
taille: file → entier Fonction taille ( D F:file): entier
Début
Si F=file-vide() alors retourner 0
Sinon retourner (1 + taille(retireréfiler(F))
fsi
Fin
L'implémentation contiguë des files se fait de manière un peu particulière du fait de réaliser les
opérations d'ajout et de suppression des deux extrémités de cette structure.
Une première solution qui vient a l’esprit, est de représenter une file à l’aide d’un tableau pour
contenir ses éléments et deux champs particuliers tête et queue indiquant respectivement l'indice du
premier élément de la file (dans le tableau) et l'indice de la première case libre après le dernier
élément de la file. Les opérations d'ajout des éléments d’un côté (queue de la file) et de suppression
de l’autre côté (tête de la file) sont prises en charge par les déplacements respectifs des indices tête
et queue.
Ainsi, remarquons que ces indices augmentent toujours et donc le tableau devra être très grand,
même s’il ne contient que très peu d’élément.
Pour éviter cet inconvénient, on peut imaginer plusieurs solutions, parmi lesquelles :
Le décalage des éléments de la file vers la gauche à chaque suppression (solution coûteuse
en temps machine) ;
Le décalage des éléments de la file vers la gauche à la saturation (solution aussi
coûteuse) ;
Utilisation d'un tableau "circulaire" de taille Lmax fixe et si un des indices queue ou tête
atteint Lmax, sa valeur est réinitialisée à 1.
C'est cette dernière solution que nous allons adopter pour représenter une file de manière contiguë
dans ce cours. La figure suivante explique cette représentation pour une file de caractères
F={A,B,C,D,E}.
1 2 3 4 5 6 7 8=Lmax
E A B C D
5 tête plein 0
2
queue
Notons que dans ce cas la file est saturée lorsque la valeur de l'indice queue atteint celle de tête
(voir figure ci-dessous).
1 2 3 4 5 6 7 8=Lmax
E F G H A B C D
5 tête plein 1
5
queue
Cette situation peut aussi représenter le cas d'une file vide. Afin de distinguer entre ces deux
situations, nous utilisons une entité supplémentaire: Plein (de type booléen) pour indiquer si la file
est pleine ou non.
1 2 3 4 5 6 7 8=Lmax
1 tête plein 0
1
queue
Remarques:
1. Rappelons que dans cette représentation des files, l'ensemble des valeur des deux indices
tête et queue du tableau Tab est: [1..Lmax, 1..Lmax,1..Lmax, …], c.à.d., une fois qu'ils
atteignent la valeur Lmax, ils sont réinitialisés à 1.
2. Nous avons alors défini deux nouvelles opérations notées: et Ө pour l'incrémentation et la
décrémentation de ces indices. Ces deux opérations permettent de garder les deux indices
tête et queue dans l’intervalle [1..Lmax].
3. Nous remarquons que l'ajout des éléments dans une file implémentée de manière contiguë
n'est pas conditionné par la taille du tableau, au-delà de cette taille, les éléments vont être
écrasés. Ce cas peut être testé et corrigé au niveau de l'algorithme appelant cette fonction
(enfiler).