Structures de Données - Ecole Mohammadia d`ingénieurs

publicité
Université Mohammed V- Agdal
Ecole Mohammadia d'Ingénieurs
Département Génie Informatique
Les Piles
Définition
- Une pile est une liste linéaire d
d'éléments
éléments (entiers,
(entiers …))
où l'ajout et la suppression d'un élément se font
du même côté.
Sommet
Structures de Données
- Si la pile n'est pas vide, l'élément accessible est le
dernier ajouté et qui se trouve au sommet de la pile
 Protocole LIFO: Last In First Out
Exemple : Utilisation de la pile en informatique:
• Journalisation des mises à jour pour réaliser la
fonction “undo” (logiciels de bureautique p.e.)
Par: Mr N.EL FADDOULI
Année Universitaire:2013/2014
EMI/ Structures de Données / N. El Faddouli
• Allocation de la mémoire pour les variables locales
lors de l’exécution des procédures
EMI/ Structures de Données / N. El Faddouli
33
1
Les Piles
Les Piles
- Les deux opérations principales sont:
Exemple d'utilisation de pile:
Empiler: ajoute un élément au dessus du sommet de
la pile.
Dépiler: supprime l'élément au sommet de la pile
si elle n'est pas vide.
Inverser une chaîne S
Algorithme:
P: Pile de caractères
N Longueur(S)
P
Pour
i 0 à N-1
N1
Empiler (S[i], P)
Pour i 0 à N-1
S[i]  Sommet(P)
Depiler (P)
- D'autres opérations sont possibles :
Implémentation statique avec un tableau:
InitPile : Cree une pile vide.
- La pile est représentée par un enregistrement
contenant les champs suivants:
Sommet: Retourne l'élément au sommet de la pile
- L'indice du sommet de la pile: un entier
- Un tableau des éléments de la pile.
qui doit être non vide.
pile est vide ou non et
PileVide: Détermine si la p
- Il faut faire un contrôle de taille lors de l'empilement
pour
éviter
un
débordement
(la pile ne doit pas être pleine)
retourne Vrai ou Faux.
EMI/ Structures de Données / N. El Faddouli
- Ce tableau peut être statique (taille maximale fixée )
ou dynamique (réservation dynamique du tableau) .
34
EMI/ Structures de Données / N. El Faddouli
35
2
Les Piles
Les Piles
Implémentation statique avec un tableau:
int Empiler (Pile *P, int X)
1 Pile avec un tableau statique: Pile d
1d'entiers
entiers
{
if (PilePleine(*P)) return 0;
typedef struct
{ int S; /* indice du sommet de la pile */
else {
int T[100]; /* Tableau statique */
(*P).S ++; /* P->S ++; */
} Pile;
Pil
((*P)
P).T
T [ ((*P)
P).S
S ] = X; //* P->T [ P->S ] = X ; *//
return 1;
Pile InitPile() { Pile P; P.S = -1; return P; }
}
}
int PileVide(Pile P) { if (P.S == -1) return 1;
else
return 0; }
int PilePleine(Pile P) { if (P.S == 99) return 1;
int Depiler (Pile *P)
else return 0;}
{
int Sommet(Pile P,
P int *x)
* ) { if ( ! PileVide(P) )
if (PileVide(*P))
(Pil Vid (*P)) return
t
0
0;
{*x = P.T[P.S]; return 1;}
else {
(*P).S -- ; /* P->S -- */
else return 0;
return 1;
}
 Il faut vérifier si la pile n'est pas vide avant de
dépiler ou prendre le sommet de la pile.
EMI/ Structures de Données / N. El Faddouli
36
}
}
EMI/ Structures de Données / N. El Faddouli
37
3
Les Files
Les Files
Définition
- Les opérations sur les files sont:
- Une file est une liste linéaire d
d'éléments
éléments où les
insertions se font d'un côté et les suppressions de
l'autre côté.
Défiler
InitFile: Cree une file vide.
Tête : Retourne l'élément en tête de la file qui doit être
non vide.
Enfiler: Insère un élément à la fin de la file.
file
Enfiler
Défiler: Supprime l'élément en tête de la file qui doit
être non vide.
FileVide: Teste si la file est vide et retourne vrai ou
- Les noms spécifiques pour ces opérations sont
Enfiler pour insérer et Défiler pour supprimer.
faux
Implémentation statique par un tableau:
- Les opérations sur les files sont syntaxiquement les
- Simplicité d'implémentation.
mêmes que sur les piles ; c'est par leur effet qu'elles
- Quand le nombre d'insertions est à priori limité.
diffèrent: l'élément supprimé est le premier arrivé
- Tableau contenant les éléments de la file.
dans la file.
- Deux indices, représentant respectivement le début
- Une file se comporte comme une file d
d'attente;
attente;
( suit le protocole First In First Out (FIFO) )
- Opération supplémentaire: FilePleine qui détermine si
- Exemple d'utilisation de file: Documents à imprimer, ...
EMI/ Structures de Données / N. El Faddouli
ett la
l fin
fi de
d la
l file.
fil
38
une file est pleine.
EMI/ Structures de Données / N. El Faddouli
39
4
Les Files
Les Files
int FileVide( File F)
- Implémentation en langage C:
{ return ( F.Q
F Q == 0); }
typedef struct
{ int N; /* Nombre maximal d'éléments*/
int Tete( File F)
int T, Q; /* tête et queue de file*/
{ return (F.E [ F.T ] ); }
int *E;
E; //* représente les éléments de la file
file*//
int FilePleine( File F)
} File;
{ return (F.Q == F.N) ; }
Version 1:
-
La tête T de la file ne change pas (T = 0)
-
La
queue
Q
de
la
file
contient
int Enfiler ((File *F,, int a))
l'indice
{
if (FilePleine (*F)) return 0;
du dernier élément ajouté dans la file.
{
{ File F ;
F.N = a ;
F->E [ F->Q ] = a;
else
File InitFile (int a) /* file de a élément*/
(*F).E[ (*F).Q ] = a;
/* Taille maximale de la file*/
(*F).Q ++;
F.T = 0;
return 1;
F Q = 0;
F.Q
}
F->Q ++;
}
F.E = (int *) malloc( a * sizeof(int) );
return (F); }
EMI/ Structures de Données / N. El Faddouli
40
EMI/ Structures de Données / N. El Faddouli
41
5
Les Files
Les Files
int Defiler (File *F)
Version 2: File circulaire
{
- Éviter
É
le décalage des éléments au défilement.
int i ;
Exemple: File F de Taille maximale 3
if (FileVide (*F)) return 0;
( on prévoit 4 cases: Taille =4 )
else
{
/* Suppression du premier élément */
Après les opérations: Enfiler(F, ‘X’);
T
for (i=0; i<(*F).Q - 1; i++ )
(*F).E [ i ] = (*F).E [ i+1 ];
Q
X
((*F)
F).Q
Q --;;
Après les opérations: Enfiler(F, ‘Y’); Enfiler(F, ’Z’);
return 1;
T
}
Q
}
Le temps d'exécution de la fonction Defiler dépend
du nombre d'élément de la file (peut être N éléments)
Les autres fonctions ont un temps d'exécution
 Comment faire pour que le temps d'exécution de
Defiler soit invariant lui aussi? (Voir la version 2)
Y
Z
 File pleine
Après les opérations: Défiler( F) ; Enfiler(F, ‘R’);
Q
invariant.
EMI/ Structures de Données / N. El Faddouli
X
T
Y
Z R
 File pleine
42
EMI/ Structures de Données / N. El Faddouli
43
6
Les Files
Les Files
typedef struct
int Enfiler (File *F, int a)
{ int N; /* Nombre maximal */
int T, Q;
/* tête et queue de file*/
int *E;
/* représente les éléments de la file*/
{ if (FilePleine (*F)) return 0;
else
{ F-E [ ?F-Q
] = a;] = a;
F-Q = ?(F-Q +1 ) % F-N ;
} File;
return 1;
File InitrFile (int a)
}
{ File F ;
}
F.N = a ; F.T = 0; F.Q = 0;
int Defiler (File *F)
F E = (int
F.E
(i t *) malloc(
ll ( a * sizeof(int)
i
f(i t) );
)
{ if (FileVide (*F)) return 0;
return (F); }
else { F-T = ?( ;F-T + 1) % F-N ;
return 1;
}
int Tete(File F)
}
{return F.E [ F.T ]; }
int FilePleine( File F)
{ if (F.T== (F.Q+1) % F.N) return 1;
else return 0; }
int FileVide( File F)
{ if ( F.T == F.Q ) return 1; else return 0; }
EMI/ Structures de Données / N. El Faddouli
44
EMI/ Structures de Données / N. El Faddouli
45
7
Exercice 1
Exercice 1
- Pour traduire une expression arithmétique (infixe) en
une expression en notation polonaise, il faut :
Évaluation des expressions Postfixées
1- Convertir la partie la plus prioritaire
- Notation infixe: l’opérateur se trouve entre les
2- La partie convertie est ensuite considérée comme
un opérande.
deux opérandes. Exemple: A+B.
Exemple : (A+B)*C  (AB+)*C  AB+C*
- Deux autres notations existent:
(A+B)*(C-D)  (A+B)(C-D)*  AB+CD-*
1- La notation préfixée: l’opérateur est placé avant
Si on considère l’opérateur d’exponentiation noté par $:
les opérandes. Exemple: +AB.
A$B*C-D+E/P/(G+H)  ……………………………….
postfixée (p
(polonaise):
) l’opérateur
p
est
2- La notation p
placé après les opérandes. Exemple: AB+.
Remarques:
- Pas de parenthèses dans les expressions postfixées.
- On doit connaître la priorité des opérateurs. Quand on
- L’ordre des opérateurs  l’ordre des opérations.
écrit A+B*C, c’est équivalent à: A+(B*C).
- Pour convertir l’expression A+(B*C) en postfixée on
Un opérateur
U
é t
d
dans
une expression
i
postfixée
tfi é
s’applique aux deux opérandes qui le précèdent.
effectue les étapes suivantes :
- Ces opérandes peuvent à leur tour être le résultat de
A+(B*C)  A+(BC*)  ABC*+
EMI/ Structures de Données / N. El Faddouli
l’application d’un opérateur.
46
3 4 5 *+
= 3+20 = 23
34+5*
= 7 * 5 = 35
EMI/ Structures de Données / N. El Faddouli
47
8
Exercice 2
Exercice 1
Algorithme général :
On utilisera une pile
pile, PileOperande
On veut créer une file d’attente d’une imprimante. Cette
Pour i 0 à Longueur(E) -1
file d’attente contient des fichiers à imprimer sachant
Si E[ i ] est un opérande alors
qu’un fichier est caractérisé par:
Empiler (PileOperande, E[ i ] )
 Un nom ( Nom )
Sinon
 Le nombre de page (NP)
Sommet (PileOperande, val1 )
1) Définir la structure Document représentant un
Depiler (PileOperande)
fichier.
Sommet (PileOperande
(PileOperande, val2 )
Depiler (PileOperande)
2) Définir la structure File représentant une file
Res  appliquer E[ i ] à val2 et val1
d’attente de fichier (document à imprimer).
Empiler ( PileOperande, Res)
3)) Réécrire les fonctions:  InitFile
Fin Pour
 Tete
Sommet (PileOperande, Resultat )
 Enfiler
Depiler(PileOperande)
Remarque: Les autres fonction restent inchangées.
Ecrire "Résultat
Résultat de calcul de"
de , E , " est " , Resultat
T.A.F: Ecrire la fonction: float
Calcul( char E[ ]) qui
fonctions
retourne le résultat de l’expression postfixée E.
EMI/ Structures de Données / N. El Faddouli
4) Écrire un programme principal pour tester ces
48
EMI/ Structures de Données / N. El Faddouli
49
9
Les Listes chaînées
Les Listes chaînées
Un tableau:
Opérations sur une liste chaînée:
- Taille Fixe
- Les éléments en mémoire sont contigus.
C opérations
Ces
é ti
sontt basées
b é sur la
l manipulation
i l ti des
d
liens
- Difficulté de redimensionner le tableau.
- Simplicité d'ajout d'un élément.(ajout de 5 entre 8 et 1)
- realloc permet de redimensionner un tableau avec
20
éventuellement un déplacement en mémoire de ses
6
8
1
éléments
7
5
 realloc coûteuse en temps de traitement.
Vs un tableau:
Exemple: int *t =(int *) malloc (4 * sizeof(int));
….
Il
t = (int *) realloc ( t, 20 * sizeof(int));
suivront la position d'insertion.
Une liste chaînée:
faut
décaler
à
droite
les
cases
qui
- Simplicité de suppression ( supprimer 8 par exemple)
- Un ensemble d'éléments non contigus organisés
20
séquentiellement.
6
8
1
5
7
Vs un tableau:
20
noeud
6
8
1
7
Il
décaler
à
gauche
les
cases
qui
suivent l'élément à supprimer.
lien
EMI/ Structures de Données / N. El Faddouli
faut
50
EMI/ Structures de Données / N. El Faddouli
51
10
Les Listes chaînées
Les Listes chaînées
Comment représenter les nœuds et les liens?
Structure en C représentant un noeud
- Un
U nœud
d estt une structure
t
t
contenant:
t
t
Exemple: Une liste d'entiers
 les données utilisateur (entier, réel, …).
typdef struct Element
(les éléments de la liste)
{
 un pointeur ((lien)) vers le nœud suivant.
int V ;
20 1000 
V
Suiv
// une donnée utilisateur
struct Element *Suiv; //pointeur sur l'élément suivant
6
} Nœud;
Adresse = 1000
Une liste vide:
- Le dernier nœud a un lien NULL
L'initialisation de l'en-tête avec la valeur NULL permet
6
d'indiquer une liste vide.
Exemple:
- On mémorise l'adresse du premier nœud dans un
void main()
pointeur appelé l'en-tête de la liste chaînée.
{ Nœud *T;
T

20

T
T = NULL;
….
……
}
EMI/ Structures de Données / N. El Faddouli
52
EMI/ Structures de Données / N. El Faddouli
53
11
Les Listes chaînées
Les Listes chaînées
Insérer un élément au début d'une liste
(2)
Le champ Suiv du nouveau nœud doit pointer
sur le
l premier
i nœud
d de
d la
l liste.
li t
Nœud * InsererDebut ( Nœud *T, int X)
T
Le nouvel en-tête
de la liste après
ll'insertion
insertion
T

Entier à insérer
au début de la
liste
En-tête
de la
liste

P
20


6

20

X
6

…

…
P->Suiv = T;
 Le nouvel en-tête de la liste est: P
(1) Créer un nouveau nœud pointé par un pointeur P
et contenant l'entier X.
Nœud * InsererDebut ( Nœud *T, int X)
{
P

Nœud * P = (Nœud *) malloc ( sizeof (Noeud) );
X
Nœud *P;
P->V=X;
P = (Nœud *)) malloc ( sizeof (Noeud) );
P->Suiv = T;;
return P;
P->V = X; /* ou (*P).V = X
EMI/ Structures de Données / N. El Faddouli
*/
}
54
EMI/ Structures de Données / N. El Faddouli
55
12
Les Listes chaînées
Les Listes chaînées
Exercice 1
Afficher une liste chaînée
É
Écrire
un programme principal (main)
(
) permettant à
void AfficherListe ( Nœud *T)
l'utilisateur de saisir plusieurs entiers jusqu'à ce qu'il
veuille s'arrêter. Chaque valeur saisie doit être insérer
T
au début d'un liste chaînée (appel de InsererDebut).
En-tête de la liste

20
P



6
P
…

(1) Utiliser un pointeur P initialisé à T.
(2) Tant Que P  NULL
- Afficher le champ V du nœud pointé par P.
- Positionner P sur le nœud suivant
- Revenir à (2)
EMI/ Structures de Données / N. El Faddouli
56
EMI/ Structures de Données / N. El Faddouli
57
13
Les Listes chaînées
Les Listes chaînées
void AfficherListe ( Nœud *T))
{ Nœud *P = T;
while ( P != NULL)
/* ou while ( P ) */
{ printf("%d \t", P->V ); P = P->Suiv; }
}
void AfficherListe ( Nœud *T)
{
if ( T != NULL)
{ printf("%d \t", P->V ); AfficherListe (T->Suiv); }
}
Exercice 2
- Écrire et faire appel à une fonction récursive qui
retourne le nombre d'éléments d'une liste chaînée.
int Taille ( Nœud *T)
EMI/ Structures de Données / N. El Faddouli
58
EMI/ Structures de Données / N. El Faddouli
59
14
Les Listes chaînées
Les Listes chaînées
Déterminer l'adresse du dernier noeud.
Nœud * DernierNoeud ( Nœud *T))
Nœud * DernierNoeud ( Nœud *T)
Adresse du
dernier noeud
{
En-tête de la liste
Nœud *P = T;
if (T == NULL) return T;
T

while ( P->Suiv != NULL)
20
P



6
P
…

P = P->Suiv;
7
P
/* ou while ( !P->Suiv ) */
retrun P;

}
(1) Utiliser un pointeur P initialisé à T.
Cas Particulier
(2) Tant Que P->Suiv  NULL
- Si la liste est vide: T == NULL
- Positionner P sur le nœud suivant
 On ne peut pas parler de P->Suiv.
- Revenir à (2)
EMI/ Structures de Données / N. El Faddouli
60
EMI/ Structures de Données / N. El Faddouli
61
15
Les Listes chaînées
Les Listes chaînées
(2) Stocker dans un pointeur Q l'adresse du dernier
noeud.
Insérer un élément à la fin d'une liste
T

Nœud * InsererFin ( Nœud *T, int X)
Le nouvel en-tête En-tête de
la liste
de la liste après
l insertion
l'insertion
Q
Entier à insérer à
la fin de la liste

20
6

T

P
20


6
…

…
7

X

(3) Faire le chaînage entre les deux nœuds pointés
7
respectivement par Q et P.
P
(1) Créer un nouveau nœud pointé par un pointeur P
Q->Suiv = P ;
Nœud * InsererFin ( Nœud *T, int X)
et contenant l'entier X.
{ Nœud *P, *Q;
P

P = (Nœud *) malloc ( sizeof (Noeud) );
X
P->V=X; P->Suiv = NULL;
Nœud *P;
if ( T == NULL) return P;
P = (Nœud *)) malloc ( sizeof (Noeud) );
P->V = X; /* ou (*P).V = X
Q = DernierNoeud( T ); Q->Suiv = P;
*/
return T;
P->Suiv = NULL;
EMI/ Structures de Données / N. El Faddouli
}
Cas particulier: Liste vide : T = NULL
62
EMI/ Structures de Données / N. El Faddouli
63
16
Les Listes chaînées
Les Listes chaînées
Supprimer le premier nœud:
Nœud * SupprimerDebut
pp
( Nœud *T))
Nœud * SupprimerDebut ( Nœud *T)
Le nouvel en-tête
de la liste après la
suppression
P
T

20

{
Nœud *P = T;
En-tête de la liste
if (T == NULL) return T;

6
T = T->Suiv ;

…
free ( P ) ;
7
retrun T ;
(1) Mémoriser la valeur de T dans un pointeur P.
}
Nœud *P;
Cas particulier
P = T;
- Liste vide : T == NULL
(2) Positionner T sur le deuxième nœud.
T = T->Suiv;
((3)) Libérer l'espace
p
occupé
p p
par le nœud p
pointé p
par P.
free(P);
(4) Retourner T .
EMI/ Structures de Données / N. El Faddouli
64
EMI/ Structures de Données / N. El Faddouli
65
17
Les Listes chaînées
Les Listes chaînées
Supprimer le dernier nœud:
Nœud * SupprimerFin
pp
( Nœud *T))
Nœud * SupprimerFin ( Nœud *T)
Le nouvel en-tête
de la liste après la
suppression
{
Nœud *P = T;
En-tête de la liste
P
T

if (T == NULL) return NULL;

if (T->Suiv == NULL) { free( T ) ; return NULL; }
20

…...
9

while(P->Suiv->Suiv)
7
P = P->Suiv;
P >Suiv;
(1) Mémoriser la valeur de T dans un pointeur P.
free ( P->Suiv ) ;
Nœud *P;
P->Suiv = NULL;
P = T;
retrun
t
T;
(2) Positionner P sur l'avant dernier nœud.
}
(3) Libérer l'espace occupé par le dernier nœud.
free(P->Suiv);
Cas particuliers
(4) Le
L champ
h
S i du
Suiv
d nœud
d pointé
i té par P reçoitit la
l
- Liste vide : T == NULL
valeur NULL.
- Liste contenant un seul noeud : T->Suiv == NULL
P->Suiv = NULL;
EMI/ Structures de Données / N. El Faddouli
66
EMI/ Structures de Données / N. El Faddouli
67
18
Les Listes chaînées
Les Listes chaînées
Représentation dynamique d’une pile
Représentation
p
dynamique
y
q d’une pile
p
1. Définir une structure Pile représentant une liste
d’entiers.
2 Ecrire
2.
E i lles ffonctions
ti
suivantes:
i
t
Pile * Empiler( Pile *P, int x)
Pile * Depiler (Pile *P)
int Sommet(Pile *P, int *x)
int PileVide(*P)
EMI/ Structures de Données / N. El Faddouli
68
EMI/ Structures de Données / N. El Faddouli
69
19
Les Listes chaînées
Les Listes chaînées
Représentation dynamique d’une pile
Représentation
p
dynamique
y
q d’une file
1. Définir une structure Nœud représentant une liste
d’entiers.
2 Définir
2.
Défi i une structure
t t
Fil
File contenant
t
td
deux pointeurs
i t
de type Nœud.
3. Ecrire les fonctions suivantes:
File InitFile( )
Créer une file dont les deux pointeurs
sont égales à NULL.
void Enfiler ( File *F, int x)
void Defiler (File *F)
int Tete(File *F, int *x)
int FileVide(File *F)
EMI/ Structures de Données / N. El Faddouli
70
EMI/ Structures de Données / N. El Faddouli
71
20
Les Listes chaînées
Les Listes chaînées
Représentation dynamique d’une file
EMI/ Structures de Données / N. El Faddouli
Représentation dynamique d’une file
72
EMI/ Structures de Données / N. El Faddouli
73
21
Téléchargement