Structure de pile
Judicaël Courant 2017-W50-4 (14 décembre)
Transcription des transparents passés en cours
Table des matières
1 La structure de pile 1
1.1 Motivations . . . 1
1.2 Structure de pile . . . 3
2 Exercices 4 2.1 Chaînes bien parenthésées . . . 4
2.2 Calculatrice en polonaise inversée . . . 4
2.3 Percolation . . . 5
3 Implantation d’une pile 5 3.1 Introduction . . . 5
3.2 Avec des tableaux statiques . . . 5
3.3 Implantation avec des tableaux dynamiques . . . 6
3.4 Implantations objet . . . 7
4 Annexes 8
1 La structure de pile
1.1 Motivations Introduction
Il existe de nombreux algorithmes dans lesquels on veut manipuler des ensembles d’objets.
Objectif
L’objectif de ce cours est de montrer :
— qu’un même besoin se retrouve dans plusieurs problèmes de programmation ;
— une notion, appelée structure de pilequi répond à ces besoins ;
— comment implanter et utiliser une structure de pile.
Fonction «retour arrière» d’un navigateur web
Un navigateur web doit stocker les URL des dernières pages visitées pour proposer la fonction «retour arrière».
Besoins
— Garder en mémoire un ensemble d’URL ;
— Ajouter une nouvelle URL (quand on va sur une nouvelle page) ;
— Récupérer la dernière adresse mise ;
— Enlever la dernière adresse mise (l’avant-dernière devient alors la dernière, etc.).
Fonction «annuler» d’un traitement de texte
Objectif : permettre de revenir à un état antérieur du document en cours d’édition.
Besoins :
— Garder un ensemble d’état du document/d’actions effectuées ;
— Ajouter un élément à cet ensemble (quand on modifie le document) ;
— Récupérer le dernier état du document/la dernière action effectuée ;
— Enlever le dernier état du document/la dernière action effectuée (lorsqu’on annule une commande).
Un besoin commun
On retrouve dans ces exemples les mêmesbesoins :
— stocker un ensemble de données ;
— ajouter un élément à l’ensemble ;
— récupérer le dernier élément mis ;
— enlever le dernier élément mis.
Objectif
Objectif : programmerune seule fois de quoi répondre à ces besoins.
Modifier un programme pour une nouvelle situation est :
— compliqué ;
— coûteux.
Le Saint-Graal de la programmation
Ne programmer qu’une seule fois ce qui correspond à un seul concept.
1.2 Structure de pile
Notion de structure de données
On aimerait avoir unestructure de données répondant à ces besoins, c’est-à-dire
— un type de données (un type d’objet Python) ;
— muni d’opérations répondant à nos besoins Définition
Structure de données=type +opérations sur ce type.
La structure de pile
Opérations requises similaires à celles offertes par une pile d’assiettes :
— stocker des assiettes ;
— ajouter une assiette ;
— voir la dernière assiette ajoutée ;
— enlever la dernière assiette.
Définition
Unestructure de pile est une structure de données dont les opérations sont :
1. creer()crée et retourne une nouvelle pile, initialement vide (en anglais :create()) ; 2. empiler(x, p)empile la valeurx sur la pilep(push(x, p)) ;
3. est_vide(p)retourneTruesi la pile est vide,Falsedans le cas contraire (is_empty(p)) ; 4. depiler(t)retourne la valeur située au sommet de la pile et l’enlève du sommet de
la pile (pop(p)). Comportement non spécifié si la pile est vide.
5. Parfois : sommet(p)retournant la valeur située au sommet de la pile (top(p)).
Remarques
— Différentes façons d’implanter cette structure de pile.
— In english : stackstructure / Last In First Outstructure (LIFO structure).
Des piles partout
— dans tout ordinateur, pour gérer les appels de fonctions, on garde une pile des variables locales et des adresses de retour ;
— dans les calculatrices en notation polonaise inversée (explication, intérêt des calcula- trices en NPL) ;
— dans le langage Postscript (devenu PDF) ;
— fonctionnalités du type «annuler» (tableur, éditeur d’image, etc.)
2 Exercices
2.1 Chaînes bien parenthésées Cadre
On considère une chaîne de caractère s, contenant divers caractères, dont possiblement (,),[et].
Objectif
Vérifier que cette chaîne estbien parenthésée.
Spécification du problème
Est définie comme «bien parenthésée» toute chaîne s vérifiant l’une des conditions sui- vantes :
1. sne contient aucune parenthèse ni crochet ;
2. scommence respectivement par(ou [et finit respectivement par)ou ]ets[1:-1]
est bien parenthésée ;
3. sest la concaténation de deux chaînes bien parenthésées.
Exemples
Bien parenthésée "(salut) [com[ment (vas-())]]tu ?"
Mal parenthésées "(salut]" et")salut("
Énoncé
Écrire une fonction bienparenthesee(s) retournant True si s est bien parenthésée et Falsesinon.
(On supposera qu’on dispose d’une structure de pile.) 2.2 Calculatrice en polonaise inversée
Description du problème
Objectif : simuler une calculatrice en polonaise inversée.
Étant donné
— une chaîne de caractères décrivant des calculs à effectuer (ex. «3 2 5 + *») ;
— une pile contenant déjà des valeurs ;
elle retourne la pile après exécution des ordres donnés.
Précisions
— Pour simplifier, on considérera qu’il y a toujours des blancs entre les arguments ou opérations dans la chaîne de caractères à exécuter.
— On veut pouvoir disposer des nombres flottants, des quatre opérations, de la mise à la puissance et de la racine carrée (sqrt).
2.3 Percolation Percolation
3 Implantation d’une pile
3.1 Introduction Objectif
Nous avons spécifié ce qu’était une structure de pile. Reste à voir comment l’implanter, c’est-à-dire la réaliser concrêtement.
3.2 Avec des tableaux statiques Introduction
— On représente une pile par un tableaut.t[0] est la première valeur empilée,t[1]la deuxième, etc.
— Pour savoir quelle est la dernière, on garde le compte du nombre d’éléments du tableau.
Conceptuellement, une pile sera donc un couple d’un tableau et du nombre de cases utilisées dans ce tableau.
Implantation Python
On veut pouvoir modifier le nombre d’éléments, donc on prendra un tableau à deux composantes : la première sera un tableau, la seconde l’index :
TAILLE_MAX = 1000 def cree():
"""Crée une nouvelle pile"""
t = [None] * TAILLE_MAX return [t, 0]
def est_vide(p):
"""Retourne True si la pile est vide, False sinon"""
return p[1] == 0 Implantation Python (suite)
def empile(x, p):
"""Empile x sur la pile p.
Précondition : p de taille au plus TAILLE_MAX-1."""
t = p[0]
i = p[1]
t[i] = x p[1] = i+1
Implantation en Python (fin) def depile(p):
"""Dépile le sommet de p et le retourne.
Précondition: p doit être non-vide."""
t = p[0]
i = p[1]
p[1] = i-1 return t[i-1]
Complexité
Quelle est la complexité des opérations ?
3.3 Implantation avec des tableaux dynamiques Introduction
Python propose des tableaux dynamiques, c’est-à-dire des tableaux auxquels on peut ajouter ou enlever des éléments (en fin de tableau).
Ces tableaux permettent trivialement de construire une structure de pile.
Implantation Python TAILLE_MAX = 1000 def cree():
"""Crée une nouvelle pile"""
return []
def est_vide(p):
"""Retourne True si la pile est vide, False sinon"""
return len(p) == 0 Implantation Python (2) def empile(x, p):
"""Empile x sur la pile p."""
p.append(x)
Implantation Python (3) def depile(p):
"""Dépile le sommet de p et le retourne."""
return p.pop() Complexité
Complexité des opérations ? Remarques
L’implantation sous forme de tableaux dynamiques : 1. est plus simple…
2. … car la difficulté est cachée dans l’implantation des tableaux dynamiques ; 3. sera privilégiée en Python puisque Python fournit des tableaux dynamiques.
Attention
Il faut connaître l’implantation avec tableaux statiques, certains langages n’offrant pas de tableaux dynamiques.
3.4 Implantations objet Motivation
Dans l’implantation avec tableaux statiques
— p[0]est le tableau des données alors quep[1]est la taille de la pile, ce qui ne facilite pas la lecture du code.
— En Python on peut faire en sorte que le nombre d’éléments soit noté p.taille et le tableaup.donnees en utilisant desclasseset desobjets.
On définit une classe Pile, avec
— des attributstailleetdonneesstockant respectivement le tableau des données et la taille de la pile ;
— des méthodes est_vide, empile,depile effectuant les opérations de test, d’empile- ment et de dépilement vues plus haut.
— une méthode spéciale __init__pour créer une pile vide.
Implantation objet (code) class Pile:
def __init__(self):
self.donnees = [None] * TAILLE_MAX self.taille = 0
def est_vide(self):
return self.taille == 0 def empile(self, x):
self.donnees[self.taille] = x self.taille += 1
def depile(self):
self.taille -= 1
return self.donnees[self.taille]
Implantation objet (utilisation)
Après ces définitions, on peut utiliser la classe pile comme suit :
# création:
p = Pile()
# empiler une valeur : p.empile(11)
# tester si la pile est vide : p.est_vide()
# dépiler : p.depile()
# on peut même accéder aux attributs de p : p.donnees
p.taille = 0 # (on vide la pile) NoteLes notions d’objet et de classe :
— sont omniprésente en Python ;
— existent dans de nombreux langages ;
— n’imposent pas une structure de donnée plutôt qu’une autre (tableaux statiques ou dynamiques).
4 Annexes
Crédits photographiques
— Capture d’écran d’un navigateur web par l’auteur, dans lequel peut être vu une partie de la photoStack of booksde Sam Howzit, sous licence Creative Commons Attribution 2.0 Generic (http://ur1.ca/iv6xo).
— Exercice sur la percolation : images tirées de Introduction to Programming in Java, Robert Sedgewick et Kevin Wayne,http://ur1.ca/ivfl3
Copyleft
Cette œuvre est libre, vous pouvez la copier, la diffuser et la modifier selon les termes de la Licence Art Libre (http://www.artlibre.org).