Piles et Files Chapitre 2
Version avec preuves.
Table des matières
1 Listes chainées 2
1.1 Listes simplement chainées . . . 2 1.2 Listes doublement chainées . . . 3
2 Pile : Pile LIFO 6
2.1 Implémentation en utilisant des listes : . . . 6 2.2 A l'aide des classes et de listes : . . . 7 2.3 Création d'une pile avec un liste chainée . . . 8
3 File : pile FIFO 10
3.1 Utilisation des listes . . . 10 3.2 A l'aide des classes et de listes : . . . 11 3.3 Utilisation d'une liste doublement chaînée . . . 12
1 Listes chainées
Une liste chaînée est une structure de donnée permettant, comme les tableaux, de stocker plusieurs valeurs.
1.1 Listes simplement chainées
Une liste simplement chainée est composée de maillon contenant une valeur et pointant vers un autre maillon.
Valeur ; Valeur Valeur Valeur Valeur
Pointeur Pointeur Pointeur Pointeur Pointeur = None
Tête Maillon Maillon Maillon Queue
On peut ainsi implémenter une liste chainée en python : Création du maillon et de la liste :
class Maillon:
def __init__(self, valeur, suivant=None):
self.valeur = valeur self.suivant = suivant class Liste_simple :
def __init__ (self) : self.tete = None
def ajout(self,element ) :
self.tete = Maillon(element, self.tete) def est_vide(self):
return self.tete == None def element_tete(self) :
return self.tete.valeur def retire(self) :
if not self.est_vide() : a = self.tete.valeur
self.tete = self.tete.suivant return a
def __str__(self) : mot = ""
maille = self.tete
while not maille == None :
mot =mot + str( maille.valeur ) + ","
maille = maille.suivant return mot
1.2 Listes doublement chainées
Une liste doublement chainée est composée de maillon contenant une valeur et deux poin- teurs : un pointant vers le maillon suivante, et autre vers le maillon précédent.
Pointeur suivant Pointeur suivant Pointeur suivant Pointeur suivant = None
Valeur Valeur Valeur Valeur
Pointeur précédent=None Pointeur précédent Pointeur précédent Pointeur précédent
Tête Maillon Maillon Queue
On peut ainsi implémenter une liste doublement chainée en python : Création du maillon et de la liste :
class Maillon:
def __init__(self, valeur, suivant=None,precedent = None):
self.valeur = valeur self.suivant = suivant self.precedent = precedent class Liste_double :
def __init__ (self) : self.tete = None self.queue = None def est_vide(self):
return (self.tete == None and self.queue == None ) def ajout_queue(self,element ) :
if self.est_vide() :
self.tete = self.queue =Maillon(element) else :
self.queue = Maillon(element,None,self.queue) self.queue.precedent.suivant = self.queue
def ajout_tete(self,element ) : if self.est_vide() :
self.tete = self.queue = Maillon(element) else :
self.tete = Maillon(element, self.tete) self.tete.suivant.precedent = self.tete def element_tete(self) :
return self.tete.valeur
def element_queue(self) : return self.queue.valeur def __str__(self) :
mot = ""
maille = self.tete
while not maille == None :
mot =mot + str( maille.valeur ) + ","
maille = maille.suivant return mot
Exercice 1 : Écrire les méthodes retire_tete et retire_queue qui éliminent les maillons et renvoient la valeur.
Correction class Maillon:
def __init__(self, valeur, suivant=None,precedent = None):
self.valeur = valeur self.suivant = suivant self.precedent = precedent class Liste_double :
def __init__ (self) : self.tete = None self.queue = None def est_vide(self):
return (self.tete == None and self.queue == None ) def ajout_queue(self,element ) :
if self.est_vide() :
self.tete = self.queue =Maillon(element) else :
self.queue = Maillon(element,None,self.queue) self.queue.precedent.suivant = self.queue
def ajout_tete(self,element ) : if self.est_vide() :
self.tete = self.queue = Maillon(element) else :
self.tete = Maillon(element, self.tete) self.tete.suivant.precedent = self.tete def element_tete(self) :
return self.tete.valeur def element_queue(self) :
return self.queue.valeur
def retire_tete(self) :
if self.est_vide() : # il n'y pas d'elements print("il y plus d'element")
elif self.tete == self.queue : # il y 1 seul element a = self.tete.valeur
self.tete = self.queue = None return a
else : # il y a au moins deux elements a = self.tete.valeur
self.tete = self.tete.suivant self.tete.precedent = None return a
def retire_queue(self) :
if self.est_vide() : # il n'y pas d'elements print("il y plus d'element")
elif self.tete == self.queue : # il y 1 seul element a = self.tete.valeur
self.tete = self.queue = None return a
else : # il y a au moins deux elements a = self.queue.valeur
self.queue = self.queue.precedent self.queue.suivant = None
return a
def __str__(self) : mot = ""
maille = self.tete
while not maille == None :
mot =mot + str( maille.valeur ) + ","
maille = maille.suivant return mot
2 Pile : Pile LIFO
La notion de pile est une notion fondamentale en informatique. Tout processeur utilise une pile.
Une pile informatique est tout à fait comparable à une pile d'assiettes. Quand on range une assiette dans une pile, on la pose sur le haut de la pile et quand on veut une assiette dans une pile, on prend celle qui est sur le dessus. Dans une pile informatique, c'est le même principe, on a accès qu'au sommet de la pile, les autres éléments étant invisibles.
Pour les piles, il existe deux opérations : la fonction d'empilement et la fonction de dépile- ment.
Dans la fonction d'empilement (on dit aussi empilage et push en anglais) on ajoute un élément au sommet de la pile.
Dans la fonction de dépilage (pop en anglais), on retourne l'élément qui est au sommet de la pile et on le supprime de la pile.
À ces deux opérateurs, il faut ajouter une fonction de création de pile. Dans la littérature anglo-saxonne, les piles se nomment stack ainsi que les les que nous verrons un peu plus tard.
Dans une pile, le dernier élément rentré est le premier qui sort ce qui donne en anglais : (Last In, First Out), on parle de façon abrégée de pile LIFO.
2.1 Implémentation en utilisant des listes :
On utilise le type liste pour implémenter notre pile.
La fonction de création de pile devient donc : Initialisation d'une pile vide :
def cree_pile () : return []
On crée ainsi une pile, initialement vide : p = cree_pile()
Exercice 2 :
1. Écrire la fonctionempile qui prend en entrée une pilep, un élémentaet ajoute l'élément à la pile.
2. Écrire la fonctionpile_vide qui renvoie le booléen correspondant au caractère vide de la pile.
3. Écrire la fonctiondepile qui prend en entrée une pile pet retourne l'élément qui est au sommet de la pile tout en le supprimant de la pile.
Correction
def cree_pile():
return []
def empile(p,element):
p.append(element) def pile_vide(p) :
return len(p)==0 # ou p == []
def depile(p) :
if pile_vide(p) : print("pile vide") else :
return p.pop()
ma_pile = cree_pile() empile(ma_pile , 5) empile ( ma_pile , 3) empile(ma_pile, 9) def somme(p) :
""" retourne la somme des elements de la pile """
s = 0
while not( pile_vide(p)) : s = s + depile(p) return s
print(somme(ma_pile)) Exercice 3 :
En utilisant les quatre fonctions précédentes, écrire une fonction sommequi somme les éléments d'une pile d'entiers.
Correction
Listing 1 La fonctionsomme
def somme_1 p : s = 0
while not (pile_vide p) : s = s + depile p
done ;
s;;
2.2 A l'aide des classes et de listes :
On peut créer la classe pile : class Pile :
def __init__ ( self) : self.contenu = []
Exercice 4 :
1. Écrire la méthodeempile qui prend un élément a et ajoute l'élément à la pile.
2. Écrire la méthodepile_vide qui renvoie le booléen correspondant au caractère vide de la pile.
3. Écrire la méthode depile qui retourne l'élément qui est au sommet de la pile tout en le supprimant de la pile.
4. Écrire la méthodelire_sommet qui retourne l'élément qui est au sommet de la pile.
Correction
#Exercice 4 class Pile :
def __init__(self) : self.contenu = []
def empile(self,element) :
self.contenu = [element]+ self.contenu def pile_vide(self) :
return len(self.contenu ) == 0 def depile(self) :
if self.pile_vide() :
print("la pile est vide") else :
a = self.contenu[0]
self.contenu = self.contenu[1:]
return a
def lire_sommet(self) : if self.pile_vide() :
print("la pile est vide") else :
return self.contenu[0]
2.3 Création d'une pile avec un liste chainée
L'idée est d'utiliser une suite de maillons, chaque maillon contenant d'une part une donnée et d'autre part un lien sur le maillon suivant de la chaîne.
class Maillon:
def __init__(self, valeur, suivant=None):
self.valeur = valeur self.suivant = suivant On peut ensuite créer la classe Pile : class Pile:
def __init__(self):
self.taille = 0 # nombre d'assiettes dans la pile self.sommet = None
Exercice 5 :
1. Écrire la méthodeempile qui prend un élément a et ajoute l'élément à la pile.
2. Écrire la méthodepile_vide qui renvoie le booléen correspondant au caractère vide de la pile.
3. Écrire la méthode depile qui retourne l'élément qui est au sommet de la pile tout en le supprimant de la pile.
4. Écrire la méthodelire_sommet qui retourne l'élément qui est au sommet de la pile.
Correction
#Exercice 4 class Pile :
def __init__(self) : self.contenu = []
def empile(self,element) :
self.contenu = [element]+ self.contenu def pile_vide(self) :
return len(self.contenu ) == 0 def depile(self) :
if self.pile_vide() :
print("la pile est vide") else :
a = self.contenu[0]
self.contenu = self.contenu[1:]
return a
def lire_sommet(self) : if self.pile_vide() :
print("la pile est vide") else :
return self.contenu[0]
3 File : pile FIFO
Dans une le de caisse d'un supermarché, la première personne qui est rentrée dans la le est la première qui doit en sortir. En informatique, nous avons aussi besoin de gérer des les.
Pour les listes, il existe deux opérations de base : la fonction de mise en le d'attente et la sortie de la le d'attente.
Dans la fonction d'ajout (add en anglais) d'un élément en n d'une liste d'attente.
Dans la fonction de prise (take en anglais) de l'élément qui est en tête de la le d'attente et que l'on le supprime de la le.
À ces deux opérateurs, il faut ajouter une fonction de création de le. Dans la littérature anglo-saxonne, les les se nomment queue. Dans une le, le premier élément rentré est le pre- mier qui sort ce qui donne en anglais : (Firt In, First Out), on parle de façon abrégée de pile FIFO.
Nous allons donc simuler les les de deux façons, l'une utilisant des tableaux et l'autre des listes.
3.1 Utilisation des listes
On utilise le type liste pour implémenter notre le.
La fonction de création de le devient donc : Initialisation d'une le vide :
def cree_file () : return []
On crée ainsi une le, initialement vide : f = cree_file()
Exercice 6 :
1. Écrire la fonctionajout qui prend en entrée une le f, un élément a et ajoute l'élément à la le.
Correction
Listing 2 La fonction empile
def ajout (p,a) : p.append(a)
2. Écrire la fonctionfile_vide qui renvoie le booléen correspondant au caractère vide de la pile.
Correction
Listing 3 La fonctionpile_vide
def file_vide (p ) : p == [] ;;
3. Écrire la fonction retire qui prend en entrée une le f et retourne l'élément qui est en tête de la le tout en le supprimant de la le.
Correction
Listing 4 La fonction depile
def retire p = p.pop(0)
3.2 A l'aide des classes et de listes :
On peut créer la classe le : class File :
def __init__ ( self) : self.contenu = []
Exercice 7 :
1. Écrire la méthodeajout qui prend un élément a et ajoute l'élément à la le.
2. Écrire la méthodefile_vide qui renvoie le booléen correspondant au caractère vide de la le.
3. Écrire la méthode retire qui retourne l'élément qui est au sommet de la le tout en le supprimant de la pile.
4. Écrire la méthodelire_debut qui retourne l'élément qui est en tête de la le.
Correction
# exercice 6 def cree_file() :
return []
def ajout(f,element):
f.append(element) def file_vide(f) :
return f== [] # ou len(f) == 0 def retire(f) :
if file_vide(f) :
print("la file est vide") else :
a = f.pop(0) return a
3.3 Utilisation d'une liste doublement chaînée
L'idée est d'utiliser une suite de maillons, chaque maillon contenant d'une part une donnée et d'autre part un lien sur le maillon suivant de la chaîne et un lien sur le maillon précédent.
class Maillon:
def __init__(self, valeur, precedent=None, suivant=None):
self.valeur = valeur
self.precedent = precedent self.suivant = suivant class File:
def __init__(self):
self.longueur = 0 self.debut = None self.fin = None
def enfiler(self, valeur):
if self.longueur == 0:
self.debut = self.fin = Maillon(valeur) else:
self.fin = Maillon(valeur, self.fin) self.fin.precedent.suivant = self.fin self.longueur += 1
def defiler(self):
if self.longueur > 0:
valeur = self.debut.valeur if self.longueur > 1:
self.debut = self.debut.suivant self.debut.precedent = None else:
self.debut = self.fin = None self.longueur -= 1
return valeur def estVide(self):
return self.longueur == 0 def __str__(self):
ch = "\nEtat de la file:\n"
maillon = self.debut while maillon != None:
ch += str(maillon.valeur) + " "
maillon = maillon.suivant return ch
q = File() q.enfiler(9) q.enfiler(2) q.enfiler(5)
print(q) q.defiler() q.enfiler(7)
print("La file est-elle vide: ", q.estVide()) print(q)
print("Longueur de la file:", q.longueur)