Académique Documents
Professionnel Documents
Culture Documents
Exercices 1 2 6 Listes
Exercices 1 2 6 Listes
1. Définition
Un pointeur est une position mémoire qui contient l'adresse d'une autre position mémoire. Généralement cette
position mémoire est une variable qui contient l'adresse d'une autre variable. Si un pointeur P contient l'adresse
d'une variable A, on dit que 'P pointe vers A'.
<idf_pointeur> est le nom de la variable pointeur qui va contenir l'adresse d'une variable de type
< type_variable_pointée>.
Exemple:
p: ^entier;
p est le nom d'un pointeur qui peut contenir l'adresses d'une variable de type entier.
algorithme pointeur ;
Var
p:^entier; /* Etape 0 */
i,g: entier;
Debut
i<-- 25;
g <-- 48;
p <-- @i; /* Etape 1 */
p <-- @g; /* Etape 2 */
Fin.
Ci-dessous est montre l’état de la Mémoire Centrale (MC) aux 2 etapes 1 et 2 ou par exemple 0x1524 est l'adresse
(en hexadécimales) en MC de la variable i et 0x1520 est l'adresse en MC de la variable g.
MC Etape 1 MC Etape 2
1
3. Accès à la variable pointée
La variable pointée est accessible en utilisant la syntaxe suivante:
<idf_pointeur> ^
Désigne le contenu de l'adresse référencée par le pointeur <idf_Pointeur>
Comme montre ci-dessous, si p contient l'adresse de i alors (p^) désigne i c'est a dire la variable pointée par p.
Donc si on écrit: p <-- @ i;
alors si on veut mettre i dans g on peut ecrire: g <-- i;
ou bien on peut écrire: g <-- p^;
car (p^) désigne le contenu de p c'est tout simplement i.
Et si on veut mettre 12 dans i on peut ecrire: i <-- 12;
ou bien on peut écrire: p^ <-- 12;
algorithme pointeur2 ;
Var
p:^entier;
i,g:entier;
Debut
i <--- 25 ;
p <--- @i;
g <--- p^; /* Etape 1 */
p^<--- 12; /* Etape 2 */
Fin.
Ci-dessous est montre l’état de la mémoire centrale aux 2 étapes 1 et 2.
MC Etape 1 MC Etape 2
Syntaxe
Allouer(<idf_pointeur>);
Exemple:
Var
p1: ^ entier;
Debut
Allouer(p1);
Allouer(p1) alloue de l'espace mémoire pour un entier et met son adresse dans p1.
Liberer(<idf_pointeur>);
Exemple:
Liberer(p1);
Libérer(p1) libère l'espace mémoire occupé par l'entier dont l'adresse est dans p1.
Var
p1,p2:^entier;
p3: ^Etudiant;
X:entier;
3
Debut
p1 <--- @X; /* p1 contient l'adresse mémoire de X */
7. Pointeurs et enregistrement
Exemple:
Algorithme InitPointeurs;
Var
p1,p2:^entier;
p3: ^Etudiant;
Debut
p1 <--- @X; /* p1 contient l'adresse mémoire de X */
Allouer(p2); /* p2 contient l'adresse mémoire d'un entier alloué dynamiquement */
Allouer(p3); /* p3 contient l'adresse d'un enregistrement de type Etudiant alloue dynamiquement
p1^ <--- 12;
p2^ <--- 27;
p3^.matricule <--- 17842;
p3^.nom <--- "Amine";
p3^.prenom <--- "Younes";
p3^.moyenne <--- 12.5;
Ecrire(p1^);
Ecrire(p2^);
Ecrire(p3^.matricule, p3^.nom, p3^.prenom, p3^.moyenne);
Liberer(p2);
Liberer(p3);
p1^ <--- 12;
p2^ <--- 27;
p3^.matricule <--- 17842;
p3^.nom <--- "Amine";
p3^.prenom <--- "Younes";
p3^.moyenne <--- 12.5;
4
Fin.
5
En revanche, par rapport aux tableaux où les éléments sont contigus dans la mémoire, les éléments d'une liste sont
éparpillés dans la mémoire.
La liaison entre les éléments se fait grâce à un pointeur.
Debut
7
Repeter
Ecrire("Donner Nombre d'éléments de la liste");
Lire(N);
Jusqu'a (N > 0);// N= mombre d'elmt de la liste
Algorithme CreationListeFiFo;
Type Pliste=^Liste ;
Liste=Enregistrement
val :entier ;
suivant : Pliste;
Fin ;
Var
tete : Pliste;
N: Entier;
8
Procedure AfficherListe(E/ L : Pliste)
Debut
Ecrire("Liste:");
Tant Que (L <> Nil)
Faire
Ecrire(L^.val);
L <--- L^.suivant;
Fait
Ecrire("Fin de Liste");
Fin;
Debut
Repeter
Ecrire("Donner Nombre d'éléments de la liste");
Lire(N);
Jusqu'a (N > 0);
EXERCICE 1 :
Soit une matrice (N,M) d’entiers. Ecrire un algorithme qui génère deux listes à partir de cette matrice.
1- La première regroupe les maximums des lignes (FIFO);
2- Et, la deuxième la somme des colonnes (LIFO).
Algorithme exo1_liste ;
Type Pliste=^EListe ;
EListe=Enregistrement
val :entier ;
suivant :Pliste ;
Fin ;
Var
I,J,N,M, Max, S: entier ;
P, prec, teteListeFifo, teteListeLifo: Pliste;
A : Tableau[1..20,1..30] de entier;
9
Début
Repeter Lire(N) ; Jusqu’à (N>0) et (N≤20) ;
Repeter Lire(M) ; Jusqu’à (M>0) et (M≤30) ;
//Lecture de la Matrice
Pour I ←1 à N Faire
Pour J ←1 à M Faire
Lire(A[I,J]) ;
Fait;
Fait ;
P ^.val←Max; J
teteListeFifo ← P; I
prec← P;
Fait;
prec ^.suivant←Nil;
10
/*création de la liste LIFO qui contient la somme des colonnes .
On traite pas la tête à part car tous les éléments se traitent de la même façon.*/
teteListeLifo ← Nil;
Pour J ←1 à M Faire
S← 0;
Pour I ←1 à N Faire
S← S+A[I,J];
Fait;
//On insère le S dans la liste Lifo
allouer (P);
P ^.val←S;
P ^.suivant← teteListeLifo;
teteListeLifo ← P;
Fait;
Fin.
EXERCICE 2 :
Soit une liste d’entiers L, écrire les actions paramétrées suivantes permettant :
1- La suppression des doublons (éléments identiques) ;
2- La suppression de la valeur minimale d'une liste;
3- La création de la liste miroir de L (avec ensuite sans création d’une nouvelle liste) ;
4- La fusion de deux listes triées d’entiers L1 et L2 en une liste triée L3 (avec ensuite sans création d’une
nouvelle liste);
Type Pliste=^EListe ;
EListe=Enregistrement
Val :entier ;
Suiv :Pliste ;
Fin ;
c) La suppression des doublons (éléments identiques) ;
11
Procedure SupDouble(E/L :Pliste) ;
Var P, Q, PREC :Pliste ;
Debut
Si L<>Nil
Alors
P←L ;
Tantque P^.Suiv<>Nil
Faire Q←P^.Suiv ; PREC←P ; /*on cherche dans Q l'identique de P, et on sauvegarde dans
PREC le précédent de Q*/
Tantque Q≠Nil
Faire Si Q^.Val=P^.Val /*On a trouvé un élément identique on le supprime*/
Alors PREC^.Suiv←Q^.Suiv ;
Libérer(Q) ;
Q← PREC^.Suiv; Q← Q^.Suiv;
Sinon PREC←Q ; /*Avancer dans la liste*/
Q←Q^.Suiv
Fsi ;
Fait ;
P←P^.Suiv ;
Fait
Fsi ;
Fin ;
Var
pMin, pMinPrcd ,p, prcd : pList;
Debut
Si (L <> Nil) Alors /* la liste contient au moins un élément*/
pMin <--- L; /* Considérer le Min comme le 1er élément */
pMinPrcd <--- Nil;
p <--- L^.svt; /* sauvegarder dans pMin l'@ de l'élément à supprimer et dans pMinPrcd son
précédent pour pouvoir faire le chainage
on parcourt la liste avec p et prcd */
prcd <--- L;
Tant Que (p <> Nil)
12
Faire
Si (p^.val < pMin^.val) Alors
pMin <--- p;
pMinPrcd <--- prcd;
Fsi
prcd <--- p;
p <--- p^.svt;
Fait
Si (pMin = L) alors /* Le minimum est le premier élément de la liste */
L <--- L^.svt;
Sinon
pMinPrcd^.svt <--- pMin^.svt;
Fsi
Liberer(pMin);
sinon ecrire ("liste vide suppression impossible");
Fsi
Retourner L;
Fin;
e) La création de la liste miroir de L (avec ensuite sans création d’une nouvelle liste)
Avec Allocation :
Fonction creationListeMiroirAvecNouvelleListe(L: pList) : pList
Var 1 8 -5 3 la liste miroir 3 -5 8 1
P, L_miroir : pList;
Debut
L_miroir <--- Nil; /* parcourir les éléments de la liste 1 et ajouter chaque élément en tête de la liste 2 de
cette façon on obtient une liste inversée*/
Tant Que (L <> Nil)
Faire Allouer(P) ;
P^.Val←L^.Val ;
P^.Suiv← L_miroir ;
L_miroir ←P ;
L←L^.Suiv ;
Fait ;
retourner L_miroir;
13
Fin;
Sans Allocation: Créer une liste miroir de L sans nouvelles allocation (ça revient à inverser la liste).
Procedure creationListeMiroirSansNouvelleListe(E/S L: pList) : pList
Var
P, Prec, Suiv : pList;
Debut
/* initialiser Prec a Nil. mettre dans p l'adresse du 1er élément de la liste
Chaque élément va avoir son suivant le précédent de la liste originale,
Le premier élément de la liste originale aura comme suivant Nil */
P <--- L;
Prec <--- Nil;
Tant Que (P <> Nil)
Faire
/* le courant est p, sauvegarder dans Suiv l'adresse du suivant */
Suiv <--- P^.suiv;
P^.suiv <--- Prec; /* le suivant de p devient le précédent */
Prec <--- P; /* à la prochaine itération le courant devient le précédent */
P <--- Suiv; /* et le suivant devient le courant */
Fait
L<-- Prec; // la tête de la liste miroire
Fin;
f) La fusion de deux listes triées d’entiers L1 et L2 en une liste triée L3 (avec ensuite sans création d’une
nouvelle liste);
Fonction FusionL1L2AvecAlloc(L1, L2: pList) : pList
Var
L, p, prec: pList;
Debut
Si ((L1 <> Nil) et (L2 <> Nil)) Alors
Allouer(p);
Si (L1^.val < L2^.val) Alors
p^.val <--- L1^.val; /*on aurai pu faire Allouer(L); L^.val <--- L1^.val; */
L1 <--- L1^.svt;
Sinon
14
p^.val <--- L2^.val;
L2 <--- L2^.svt;
Fsi ;
L <--- p; // L la tête de la nouvelle liste
prec <--- p; // nouvelle liste FIFO, on fait toujours des insertion en fin, on aura besoins du précédent
Tant Que ((L1 <> Nil) et (L2 <> Nil))
Faire
Allouer(p);
Si (L1^val < L2^.val) alors
p^.val <--- L1^.val;
L1 <--- L1^.svt;
Sinon
p^.val <--- L2^.val;
L2 <--- L2^.svt;
Fsi ;
prec^.svt <--- p;
prec <--- p;
Fait ;
/* Une des deux listes L1 ou L2 est terminée. Il faut ajouter les valeurs qui manquent de L1 ou L2 */
Tant Que (L1 <> Nil)
Faire
Allouer(p);
p^.val <--- L1^.val;
L1 <--- L1^.svt;
prec^.svt <--- p;
prec <--- p;
Fait
Tant Que (L2 <> Nil)
Faire
Allouer(p);
p^.val <--- L2^.val;
L2 <--- L2^.svt;
prec^.svt <--- p;
15
prec <--- p;
Fait
prec^.svt <--- Nil;
Sinon /*le sinon du premier Si ((L1 <> Nil) et (L2 <> Nil)) donc ou bien L1=Nil ou L2=Nil ou les deux sont
vides à l'entrée*/
Si (L1 <> Nil) alors /* liste L2 vide
/* Créer la liste L qui contient tous les éléments de L1, mais le traitement du premier est à part!*/
Allouer(p);
p^.val <--- L1^.val;
L1 <--- L1^.svt;
L <--- p;
prec <--- p;
/* Ajouter les éléments après le 1er élément de L1 */
Tant Que (L1 <> Nil)
Faire
Allouer(p);
p^.val <--- L1^.val;
L1 <--- L1^.svt;
prec^.svt <--- p;
prec <--- p;
Fait
prec^.svt <--- Nil; //dernier element
Sinon /* le sinon de Si (L1 <> Nil) donc L1=Nil
Si (L2 <> Nil) alors
/* Allouer le 1er element */
Allouer(p);
p^.val <--- L2^.val;
L2 <--- L2^.svt;
L <--- p;
prec <--- p;
/* Ajouter les éléments apres le 1er elements de L2 */
Tant Que (L2 <> Nil)
Faire
16
Allouer(p);
p^.val <--- L2^.val;
L2 <--- L2^.svt;
prec^.svt <--- p;
prec <--- p;
Fait
prec^.svt <--- Nil;
Sinon /* Cas ou L1=Nil et L2=Nil */
L <--- Nil;
Fsi
Fsi
Fsi
Retourner L;
Fin;
17
Faire
Si (L1^val < L2^.val) Alors
prec^.svt <--- L1;
L1 <--- L1^.svt;
Sinon
prec^.svt <--- L2;
L2 <--- L2^.svt;
Fsi
prec <--- prec^.svt;
Fait
/* Ajouter les liens qui manquent de L1 ou L2 */
Si (L1 <> Nil) alors
prec^.svt <--- L1;
Sinon
prec^.svt <--- L2;
Fsi
Sinon /* sinon du Si ((L1 <> Nil) et (L2 <> Nil))*/
Si (L1 <> Nil) alors
L <--- L1;
Sinon
L <--- L2;
Fsi
Fsi
Retourner L;
Fin;
EXERCICE 3 :
Soit L une liste d’entiers positifs. Ecrire une procédure qui permet d’éclater la liste L en deux listes : Lp contenant
les entiers pairs et Li contenant les entiers impairs. (Sans création de nouvelles listes)
19
2- Soit VAL une valeur entière donnée. Ecrire une action paramétrée permettant de créer une liste POSVAL contenant
toutes les positions de la valeur VAL dans la liste L (en LIFO).
Si L ≠ Nil
Alors
Si K>=1
Alors
Si K = 1 Alors P← L ^.Suiv ; Liberer(L); L ← P //suppression de la tete
Sinon // chercher dans Q le précédent du kieme élément et P pointe l'élement K
P ← L;
Tantque P ≠ Nil Et K>1
Faire Q ← P; P ← P^.Suiv; K ← K – 1; Fait;
Si P ≠ Nil
Q^.Suiv ← P^.Suiv ;
Liberer(P) //milieu ou à la fin
Fsi;
Fsi
Fsi;
Fsi;
retourner L;
20
Fin;
21