Vous êtes sur la page 1sur 16

Algorithmes et programmation structure

3.

LES FICHIERS

Il est possible de stocker les donnes dans des fichiers


pour pouvoir les utiliser plus tard.
Le C distingue deux catgories de fichiers, les fichiers qui
utilisent des flux de donnes dits standards et les fichiers
dits systmes qui sont beaucoup plus proches du systme
dexploitation, qui nentrent pas dans la phase
dapprentissage du C.
Un flux est une suite de donnes qui vont circuler entre
lunit centrale et ses priphriques, cran, disques. On
distingue flux de texte et flux binaires, fichiers de textes
et fichiers binaires.
Les fichiers dit binaires, les informations sont codes
telles que. Ce sont en gnral, des fichiers de nombres. Ils
ne sont pas listables.
Les fichiers dit textes ou ASCII, les informations sont
codes telles que. Ces fichiers sont listables. Le dernier
octet de ces fichiers est EOF (caractre ASCII
spcifique).
La plupart des fonctions ou primitives permettant la
manipulation des fichiers sont rangs dans la bibliothque
standard STDIO.H, certaines dans la bibliothque IO.H
pour le BORLAND C++.

3.1. Dfinition et proprits


Un fichier est un ensemble structur de donnes stock
sur un support externe (disquette, disque dur, disque
optique, bande magntique,).
Un fichier squentiel : dans des fichiers squentiels, les
enregistrements sont mmoriss conscutivement dans
lordre de leur entre et peuvent tre lus dans cet ordre. Si
on a besoin dun enregistrement prcis dans un fichier
squentiel, il faut lire tous les enregistrements qui le
prcdent, en commenant par le premier.
Un fichier squentiel est reprsent squentiellement par
la suite ordonne de ses lments, note
<x1, x2, x3,,xn>.
Les fichiers squentiels auront les proprits :
- les fichiers se trouvent ou bien en tat dcriture ou bien
en tat de lecture.
- A un moment donn, on peut uniquement accder un
seul enregistrement, celui qui se trouve en face de la tte
de lecture/ criture.
- Aprs chaque accs, la tte de lecture/ criture est
dplace derrire la donne lue en dernier lieu.
Pour de raisons defficacit, les accs un fichier se font
par lintermdiaire dune mmoire tampon (en anglais
buffer). La mmoire tampon est une zone de la mmoire
centrale de la machine rserve un ou plusieurs
enregistrements du fichier. Lutilisation de la mmoire
tampon a leffet de rduire le nombre daccs la
priphrie dune part et le nombre des mouvements de la
tte de lecture/ criture dautre part.
- Un fichier peut tre vide.
Un sous-fichier est la restriction dun fichier f un
intervalle de P (suite dlments conscutifs). P est un
ensemble fini totalement ordonn.
Exemple : f = <5, 7, 59, 67, -1, 0, 18> alors <5, 7, 59> et
<67, -1, 0, 18> sont des sous-fichiers de f. Par contre, <5,
59, 18> nest pas un sous-fichier.
Nous supposons que tout fichier peut tre schmatis par
un ruban dfilant devant une tte de lecture/ criture. On
a accs une valeur que lorsque llment correspondant
(appel lment accessible ou lment courant) est en
face de la tte de lecture/ criture. Un fichier tant une
suite finie, on introduit une marque sur le ruban (note -|)
qui permet au mcanisme dinterprtation de dtecter la

fin du fichier. Un fichier nest dfini que sil comporte une


marque.
tte de lecture/ criture

sens de dfilement
x1

x2

x3

x4

xn

-|

-----f- -----------------------f+----------------
Llment courant (x3) permet, par dfinition, de dcomposer
un fichier en deux sous-fichiers : f = f- || f+
O f- est le sous-fichier dj lu et f+ est le sous-fichier qui reste
lire. Llment courant est le premier lment de f+.
Dans cet exemple : f- = <x1, x2>, f+ = <x3,,xn>, llment
courant est x4.
Notation fest dfinie par : f- = f--|| val.
fest le fichier f- avant excution de laction : lire(f,val)

3.2. Actions primitives daccs.


Pour donner un modle du comportement dynamique dun
fichier (dfilement de voyageurs, les uns la suite des autres
devant le guichet de douane o chaque voyageur fait sa
dclaration) nous allons dfinir des actions lmentaires dites
primitives daccs la valeur de chaque lment.

3.2.1.

Dclaration.

Pour pouvoir travailler avec un fichier, un programme a besoin


dun certain nombre dinformations au sujet du fichier :
- adresse de la mmoire tampon,
- position actuelle de la tte de lecture/ criture,
- type daccs au fichier, criture, lecture,
- tat derreur,
-
Ces informations sont rassembles dans une structure du type
spcial FILE. Lorsque nous ouvrons un fichier avec la
primitive fopen, le systme gnre automatiquement un bloc du
type FILE et nous fournit son adresse.
Les tapes suivre pour traiter un fichier :
- dclarer un pointeur de type FILE*,
- affecter ladresse retourne par fopen ce pointeur,
- employer le pointeur la place du nom du fichier dans toutes
les instructions de lecture ou dcriture,
- librer le pointeur la fin du traitement par fclose.
3.2.2.
primitives daccs.
Avant de crer ou de lire un fichier, nous devons informer le
systme de cette intention pour quil puisse rserver la mmoire
pour la zone dchange et initialiser les informations
ncessaires laccs du fichier. On parle alors de louverture
du fichier.
Aprs avoir termin la manipulation du fichier, nous devons
vider la mmoire tampon et librer lespace en mmoire occup
pendant le traitement. On parle alors de la fermeture du fichier.
3.2.2.1. Ouvrir un fichier squentiel.
- En langage algorithmique
Ouvrir (nom, en criture) ou bien
Ouvrir (nom, en lecture)
<nom> est une chane de caractres constante ou une variable
de type chane qui reprsente le nom du fichier.
- En langage C fopen.
FILE * fopen(char * nom, char * mode) ;
On passe deux chanes de caractres :
nom : celui figurant sur le disque, par exemple : a:\toto.dat.
mode : a) pour les fichiers textes.
r lecture seule,
w criture seule, destruction de lancienne si elle existe.

Rakotoasimbahoaka Cyprien Robert

anne 2008

34

Algorithmes et programmation structure


a+ lecture et criture dun fichier exis-tant
(mise jour), pas de cration dune nouvelle version, le
pointeur est positionn la fin du fichier
b) pour les fichiers binaires
rb lecture seule,
wb criture seule (destruction de lanci-enne
version si elle existe),
ab+ lecture/ criture dun fichier existant
(mise jour), pas de cration dune nouvelle version, le
pointeur est positionn la fin du fichier
Exemple : ouverture dun fichier texte en lecture.
FILE *f ;
f = fopen(c:\toto.dat, r) ;
Avant de crer un fichier on doit louvrir en criture
3.2.2.2. Crer un fichier squentiel
- En langage algorithmique : crire (nom, expr).
- Les fonctions utilises en C sont :
a) int fputc(char c, FILE *f) ;
Ecrit la valeur de c la position courante du poin-teur, le
pointeur avance dune case mmoire.
- retourne le symbole de fin de fichier EOF en cas
derreur,
- f est un pointeur qui est reli au nom du fichier cible.
Exemple : fputc(A, f) ;
b) int fputw(int n, FILE *f) ;
Ecrit la valeur de n la position courante du pointeur, le
pointeur avance du nombre de cases correspondant la
taille dun entier.
Retourne n si lcriture sest bien pass.
c) int fputs(char *chaine, FILE * f) ;
Ecrit la valeur dune chane de caractres la position
courante du pointeur, le pointeur avance da la longueur
de la chane (\0 nest pas rang dans le fichier).
Retourne EOF en cas derreur.
Exemple : fputs(Bonjour !, f) ;
d) int fwrite(void *p, int taille_bloc, int nb_bloc, FILE
*f) ;
p de type pointeur, crit partir de la position courante du
pointeur du fichier nb_bloc X taille_bloc octets lus
partir de ladresse p. Le pointeur f avance dautant.
Retourne le nombre de blocs crits.
Exemple : taille_bloc = 4 (taille dun entier en C),
nb_bloc = 3, criture de 3 octets.
int tab[10] ;
fwrite(tab, 4, 3, f) ;
e) int fprintf(FILE *f, char * format, liste dexpression) ;
Rserve plutt aux fichiers ASCII. Retourne EOF en cas
derreur.
exemple : fprintf(f, %s\n, il fait beau) ;
Le pointeur avance dautant.
Cette fonction est utilise pour crer un fichier texte
Avant de lire un fichier on doit louvrir en lecture.
3.2.2.3. Lire un fichier squentiel
- En langage algorithmique : lire (nom, variable);
- Les fonctions utilises en C :
a) int fgetc(FILE *f) ; lit un caractre, mais retourne un
entier ; retourne EOF si erreur, le pointeur avance dune
case.
Exemple : char c ;
c = (char)fgetc(f) ;
b) int fgetw(FILE *f) ; lit un entier, le pointeur avance de
la taille dun entier.
Exemple int n ;
n = fgetw(f) ;
c) char * fgets(char *chane, int n, FILE *f) ; lit n-1
caractres partir de la position du pointeur et les range
dans chane en ajoutant \0.

d) int fread(void *p, int taille_bloc, int nb_bloc, FILE *f) ;


analogue fwrite en lecture. Retourne le nombre de blocs lus,
et 0 la fin du fichier.
e) int fscanf(FILE *f, char * format, liste dadresses ) ;
analogue fprintf en lecture.
Avant de quitter un fichier on doit le fermer.
3.2.2.4. Fermer un fichier squentiel
- En langage algorithmique
Fermer (nom) ;
<nom> est une chane de caractre ou une variable de type
chane qui reprsente le nom dun fichier.
Fermer un fichier en langage C : fclose(<F>) ;
<F> est un pointeur du type FILE* reli au nom du fichier que
lon dsire fermer.
Exemple : fclose(f) ;
3.2.2.5. Dtecter la fin du fichier.
Les fonctions douverture, de lecture et dcriture de fichier
donne une valeur EOF (End Of File) ou fdf. EOF ou fdf
permettent de dtecter la fin dun fichier.
En langage algorithmique : fdf(nom) retourne la valeur logique
vrai, si la tte de lecture du fichier rfrenc par <nom> est
arrive la fin du fichier ; sinon la valeur logique du rsultat
est faux
<nom> est une chane de caractres constante ou une variable
de type chane qui reprsente le nom du fichier duquel on veut
lire.
En langage C, on utilise la fonction feof(<f>) ; feof retourne
une valeur diffrente de zro, si la tte de lecture du fichier
rfrenc par <f> est arriv la fin du fichier ; sinon la valeur
du rsultat est zro.
<f> est un pointeur du type FILE* qui est reli au nom du
fichier lire.
Exemple : une boucle typique pour lire les enregistrements
dun fichier squentiel rfrenc par un pointeur f peut avoir la
forme suivante :

while( !feof(f)){
fscanf(f, %s %s\n , nom, prenom) ;

}
Consulter ce programme qui lit et affiche le contenu du fichier
C:\AUTOEXEC.BAT.
programme ch3_1.c
Dans une chane de caractres constante, il faut indiquer le
symbole\ par \\ pour quil ne soit pas confondu avec le dbut
dune squence dchappement (par exemple \n, \t).
Tableau 1 : Rsum sur fichier caractre et texte
Action
ouverture en
criture
ouverture en
lecture
fermeture
fct finfichier
criture

Algorithme
ouvrir <nom> en
criture
ouvrir <nom> en
lecture
fermer <nom>
finfichier <nom>
crire<nom>:<var>

lecture

lire<nom>:<var>

C
f=fopen(nom, w)
f=fopen(nom,r)
fclose(f)
feof(f)
fprintf(f,,adr)
fputc
fscanf(f,,adr)
c=getc(f)

3.2.2.6. Dtruire un fichier


int remove(char *nom) ;
retourne 0 si la fermeture sest bien passe.
Exemple : remove(c:\\toto.dat) ;
3.2.2.7.Renommer un fichier.
int rename(char *oldname, char *newname) ;
retourne 0 si la fermeture sest bien passe.
3.2.2.8.positionner le pointeur au dbut du fichier.

Rakotoasimbahoaka Cyprien Robert

anne 2008

35

Algorithmes et programmation structure


Void rewind(FILE * f) ;
3.3. Algorithmes traitant un seul fichier
Quelques exemples dalgorithmes mettant en jeu un seul
fichier.
3.3.1. Somme des lments dun fichier.
On se propose dcrire une fonction somme dont lentte est le suivant :
entier somme( FICHIER *f)
//spcification {f<>}=>{som=f}
Raisonnement par rcurrence : supposons traits les
premiers lments de f. on a f = f-||f+, f-<>.
Appelons s la somme des lments de f- (s=f-). On peut
crire lassertion A.
A : s=f-, (fdf(f), f+=<>) v (fdf(f), f+ <>)
On a deux cas :

f+ est vide (note f+ = <>)


Le prdicat fdf(f) est vrai (on crit fdf(f)) ; f- = f et s
contient la somme des lments de f (som=f). On
excute linstruction retour s ; et lalgorithme est
termin.

f+ nest pas vide (not f+ <>)


Le prdicat fdf(f) est faux (on crit fdf(f)) ; on peut
donc rcuprer la valeur de llment courant en
excutant linstruction lire f : c ; on ajoute le contenu de
la variable c celui de la variable s (s +=c ;)
Aprs excution des deux actions :
lire(f, c) ; // s=f-, (fdf(f), f- = f- || c )
s += c ; // s = s=f- + c s = fOn peut toujours crire lassertion A.
A : s=f-, (fdf(f), f+=<>) v (fdf(f), f+ <>)
Ces deux actions ne sont excutables que si (fdf(f)).
Do : tanque(non fdf(f)){
lire f : c ;
s += c ; }
Initialisation : il faut que A soit une assertion aprs
linitialisation. Il sensuit que f- doit contenir le premier
lment du fichier f, et que s doit tre initialis avec ce
premier lment.
ouvrir(f, en lecture) ; // f-=<>, fdf(f), f+ = f
lire(f, s) ; // f-=<x1>, s=x1.
A : s=f-, (fdf(f), f+=<>) v (fdf(f), f+ <>)
On peut donc crire lassertion A qui est linvariant de
litration.
On peut rsumer ce raisonnement par le schma suivant :
Hypothse : s = f f+ = <>
s = f
retour s ; => som = f *
f+ <>
.
=> lire f : c ; s += c ; H
Itration : tantque(non fdf(f))
Initialisation : ouvrir f en lecture ;
Lire(f, s) ; H
Lalgorithme est le suivant :
programme ch3_2.c
Remarque : dans le cas dun fichier vide, il est interdit
dcrire cet algorithme. On doit alors crire un autre plus
gnral condition de prciser la convention adopte
dans ce cas.
Convention : la somme des lments dun fichier vide est
gale zro. Avec cette convention, il suffit dexcuter,
linitialisation, les actions suivantes :

Ouvrir (f, en lecture) ; s = 0 ; qui permettent A : s=f-,


(fdf(f), f+=<>) v (fdf(f), f+ <>) dtre toujours un invariant.
La suite des algorithmes est inchange.
3.3.2. Recherche de la valeur maximale contenue dans un
fichier.
Soit un fichier f non vide, tel que lensemble des valeurs soit
muni dune relation dordre total.
On cherche une valeur m f et telle que y f, on ait m y.
Une telle valeur est dite maximale.
Len-tte de la fonction est le suivant : entier
maximum(FICHIER * f)
// spcification (f<>)(max f, maxf)
Raisonnement par rcurrence
Supposons traits les premiers lments du fichier (f = f- || f+)
et que m soit le plus grand lment de f-.
On peut crire lhypothse : m f-, m fOn a alors deux cas :

f+ = <>
f- = f, lexcution de linstruction : retour m ;
permet de terminer lalgorithme (maxi f, maxi f).

f+ <>
On lit llment courant : lire f : c ;
// m f-, m f-, f- = f- || <c>
On compare c avec m. On a de nouveau deux cas :
** m c
On peut donc crire mf-||<c> mf-, mf-.
** m < c
Lexcution de linstruction : m = c ;
permet lcriture mf- || <c> mf-, mfOn a donc une itration compose dune seule condition portant
sur la fin de fichier.
Initialisation : on suppose que le fichier f nest pas vide ; on
donne alors m la valeur x1, premire valeur du fichier f :
Ouvrir(f, en lecture) ;
lire (f, m) ;
// m f-, m f- est alors un invariant.
Le raisonnement est rsum par le schma suivant :
Hypothse : m f-, m f f+ = <>
retour m
m f-, m f- *
f+ <>
.
=> lire (f, c) ;
=> m f-, m f-, f- = f- || <c>
>> m c
H
>> m < c
=> m = c ;
H
Itration : tantque(non fdf(f))
Initialisation : ouvrir (f, en lecture) ;
lire (f, m); H
Lalgorithme est alors :
programme ch3_3.c
Pour les algorithmes prcdents, litration est toujours de la
forme :
: ouvrir (f, en lecture) ;
.
tantque(non fdf(f)){
lire (f, c) ;
traiter (c) ;
}
O traiter est une fonction quelconque agissant ou non sur le
contenu de la variable c. A chaque excution de laction lire (f,
c); le nombre dlments de f+ diminue de un. En un nombre

Rakotoasimbahoaka Cyprien Robert

anne 2008

36

Algorithmes et programmation structure


fini de pas, on obtient f- = f, f+ =<> et fdf(f), ce qui
permet darrter lalgorithme.
3.3.3. Accs un lment dun fichier
Ce problme est habituellement formul de deux
manires :

Soit on connat le rang k de llment que lon


cherche dans le fichier et on recherche alors le kime
lment du fichier,

Soit on connat la valeur de llment que lon


cherche et on lon recherche le premier lment qui
correspond cette valeur (cest--dire) la premire
occurrence).
On parle alors de recherche ou daccs :

Par position dans le premier cas,

Par valeur ou associatif dans le second.


3.3.3.1. Accs par position (accs au kme lment)
Len-tte de la fonction est :
t accesk(FICHIER *f, entier k, booleen * trouve) ;
// spcification(k>0)=>((trouve, valk = xk ) v (non trouve
, valk est indfinie)).
On peut dcomposer le fichier en deux sous-fichiers f1k-1
et fkn, do : f = f1k-1 || fkn
Pour que le kime existe, il faut que le sous-fichier fkn ne
soit pas vide (fkn <>). Dans ce cas, et si on a effectu la
lecture des k-1 premiers lments, f+ commence par le
kime lment du fichier f.
Lalgorithme est alors compos de deux parties :

Parcours des k-1 premiers lments de f (f-= f1k-1)

Ensuite, suivant que le fichier f+ est vide ou non, on


pourra donner les rsultats suivants :
** f+ = <>, trouve prendra la valeur faux (0) et
valk sera indfinie.
** f+ <>, trouve prendra la valeur vrai et valk
contiendra la valeur du kime lment en effectuant
laction lire( f, c) ;
a) construction de f- = f1k-1
Raisonnement par rcurrence
Hypothse : f-= f1k-1
i=k
f-= f1k-1
*
i<k
. >> f+ = <>
=> le kime lment nexiste pas. *
>> f+ <>
=> lire f : c
=> i += 1 ;
H
Itration : tantque((i < k)et non fdf(f))
Initialisation : ouvrir (f, en lecture) ;
i = 1; H
On obtient lalgorithme :
ouvrir (f, en lecture) ;
i=1;
tantque((i < k) et non fdf(f)){ lire (f, c) ;
i += 1 ;
}
b) suite de lalgorithme
A la sortie du tantqueon a ((i < k), (fdf(f)), soit
daprs la loi de De Morgan (i k) v fdf(f).
i > k : signifie que k 0.
En effet, i est initialis avec la valeur 1. Dautre part i
augmente de 1 lintrieur de tantque.
Si k > 0, la ngation de i < k ne peut tre que i = k. On ne
peut avoir i > k sans tre pass au pralable par la valeur

de i gale celle de k. i > k tait donc vrai linitialisation,


comme i = 1, cela signifie que k 0. Or, nous avons prcis
dans la pr-condition que k > 0 ; donc i > k ne peut jamais se
produire.
Dautre part f- = f1i-1 est linvariant que lon peut crire
lentre et la sortie du tantque.
Nous allons maintenant tudier tous les cas possibles de
lassertion (i = k) v fdf(f).
1) i = k, fdf(f)
signifie que lon a atteint la fin de fichier, et qu ce moment l
on a trouv que le rang de llment tait gal k. Le fichier a
donc k-1 lments, le sous-fichier f+ est vide et le kime lment
nexiste pas : f = f1k-1, trouve prend la valeur faux et valk est
indfinie.
2) i = k, fdf(f)
signifie quon a trouv le kime lment sans atteindre la fin du
fichier. On a donc : (f- = f1i-1, i = k) f- = f1k-1
Il sensuit que f+ = f1n avec k n ; lire f : valk permet valk de
prendre la valeur du kime lment et trouve doit prendre la
valeur vrai.
3) i < k, fdf(f)
On a parcouru tous les lments du fichier sans trouver le kime
lment. f- = f1n, f+ = <>, trouve prend la valeur faux et valk est
indfinie.
4) i < k, fdf(f)
Ce cas ne peut jamais se produire car lexpression (i = k) v
((fdf(f)) est fausse et nest donc pas une assertion.
On peut rsumer ces quatre cas dans un tableau (quon appelle
tableau de sortie).
Tableau 2 : tableau de sortie
i=k
fdf(f)
rsultat
Vrai
vrai
trouve = faux
Vrai
faux
trouve = vrai ; lire f : valk
faux (i<k)
vrai
trouve = faux
faux (i<k)
faux
impossible (tantque)
En examinant les trois premires lignes du tableau, on constate que la
valeur de trouve est identique celle de (fdf(f)). Il faut donc continuer
lalgorithme en utilisant un test sur la valeur du prdicat.
Par contre, utiliser un test sur la valeur de (i = k) (comme on aurait pu
le faire htivement), entrane une erreur dans le cas de la premire
ligne. On aurait donc crit un algorithme qui aurait fonctionn dans la
plupart des cas, sauf si par hasard on avait rencontr le cas dun fichier
contenant k-1 lments.
Do lintrt de la construction et de lanalyse du tableau de sortie
qui permet de complter le raisonnement par rcurrence.
On poursuit lalgorithme en crivant :
si(non fdf(f)){ trouve = vrai ;
lire (f, valk) ; retour valk ;
}
sinon trouve = faux ;
ou encore
trouve = non fdf(f) ;
si (trouve) { lire (f, valk) ; retour valk ; }
Une autre solution consiste initialiser trouve faux au dbut de
lalgorithme, il suffit alors de terminer lalgorithme avec :
Trouve=faux ;
si(non fdf(f)){ trouve = vrai ;
lire (f, valk) ; retour valk ;
}
Cest cette dernire solution que nous utilisons frquemment, car elle
permet dallger lalgorithme en vitant lcriture de sinon.
programme ch3_4.c
3.3.3.2. Accs associatif
Soit un fichier f et une valeur contenue dans la variable val de mme
type que les lments de f. On veut savoir si la valeur contenue dans
val est prsente dans le fichier f (= f1n).
val f signifie que i [1..n], xi = val.
Len-tte de la fonction est :
entier acces(FICHIER *f, t val)
//spcification()(trouve,valf) v (trouve, valf)

Rakotoasimbahoaka Cyprien Robert

anne 2008

37

Algorithmes et programmation structure


Raisonnement par rcurrence.
Une variable boolenne egal dfinie par :
(egal, val f-)v(egal, val f-) est utiliser pour contrler
litration.
Hypothse : val f-, egal
f+ = <>

val f

f+ <>

lire (f, c);

val f-, c =Df. >> c == val


=> val f=> egal = vrai
*
>> c val
H
Itration : tantque(non fdf(f) et non egal)
Initialisation : ouvrir (f, en lecture);
Egal = faux; H
Lalgorithme est alors :
programme ch3_5.c
Tableau 3 : Tableau de sortie
fdf(f)
egal
Rsultat : val f
vrai
vrai
trouve = vrai (val = Df)
vrai
faux
trouve = faux
faux
vrai
trouve = vrai
faux
faux
impossible (tantque)
On constate que trouve a la mme valeur que egal.
3.3.4. Fichier ordonn (fichier tri)
Dfinition : Si tous les lments conscutifs dun fichier vrifient
la relation dordre (xi xi+1), on dit que le fichier est tri par
ordre croissant. Dans la suite du cours, on appellera fichier tri
(ou ordonn) un fichier ordonn par ordre croissant.
On admettra que le fichier vide et que le fichier ne contenant
quun seul lment sont tris.
En dautres termes, la dfinition dun fichier tri :

un fichier vide est tri,

un fichier comportant un seul lment est tri,

Lalgorithme est alors :


programme ch3_6.c
3.3.4.2. Algorithme daccs un lment dans un fichier tri.
Dans le cas dun accs associatif, la relation dordre dfinie sur
lensemble des valeurs permet dviter un parcours complet des
lments du fichier. Pour conclure la non appartenance dun
lment. En gnral, laccs associatif dans un fichier ordonn
est plus rapide que dans le cas dun fichier non ordonn. On
sefforce, dans la pratique, dutiliser, chaque fois quil est
possible, un fichier tri.
On cherche crire une fonction dont len-tte est :
entier accest(FICHIER *f, val)
//spcification (f tri)(rsultat = val f)
On peut toujours dcomposer un fichier f tri et non vide en
deux sous-fichiers f et f tel que :
f = f || f, f< val f
Remarque :
Si f = <>, la relation scrit : val fSi f = <>, la relation scrit f < val.
On contrle litration par une variable boolenne infer
dfinie par : (infer, f- < val) v (infer, Df- val).
Raisonnement par rcurrence :
Hypothse : f- < val, infer
f+ = <>
Rsultat faux
f+ <>
lire(f, c) ;
f- < val, c = Df>> c < val
f- < val
>> c val
premire partie termine
infer = faux ;
Itration : tantque(non fdf(f) et infer)
Initialisation : ouvrir (f, en lecture);
infer = vrai ;

soit f = <x1, x2, ,xn>, avec n>1, le fichier f est tri


si i [1..n-1], la relation xi xi+1 est vraie.
On peut donner une dfinition rcursive :
Fichier tri dfinition rcursive :

Un fichier vide est tri,

Un fichier contenant un seul lment est tri,

(f1i tri, xi xi+1) f1i+1 tri pour i [1..n-1].


3.3.4.1. Algorithme vrifiant quun fichier est tri.
Len-tte est le suivant : boolen trie(FICHIER *f)
// spcification()(rsultat = f est tri)
Raisonnement par rcurrence :
Hypothse : f- tri, precedent = Df-, c= Df precedent > c

F nest pas tri


precedent c

*
*

precedent = c ;

f est vide donc tri

lire(f, c) ; H
Itration : tantque(non fdf(f) et (precedent c))
Initialisation : ouvrir (f, en lecture);
f+ = <>
*

f+ <>

lire(f, precedent) ;

precedent = Df>> f+ = <>

f est vide donc tri ;


>> f+ <>

lire(f, c) ;

Lalgorithme est alors :


programme ch3_7.c
Tableau 4 : tableau de sortie
fdf(f)
vrai

infer
vrai

vrai

faux

faux

vrai

faux

faux

rsultat : accest

c>val => rsultat faux

c=val => rsultat vrai


Fichier vide ou f<val
=> rsultat faux

c>val => rsultat faux

c=val => rsultat vrai


Impossible (tantque)

3.4. Algorithmes traitant plusieurs fichiers.

f- tri
. >> f+ = <>
>> f+ <>

Ces algorithmes prennent des lments sur un ou plusieurs


fichiers et construisent un ou plusieurs fichiers. Ces
algorithmes sont construits partir du parcours des lments
dun ou plusieurs fichiers (ils se terminent puisque le nombre
dlments est fini).
3.4.1. Algorithme de cration, par copie, dun fichier
Ce problme consiste crer, partir dun fichier
f=<x1, x2,,xn>, un fichier identique
g=<x1, x2,,xn >.
Algorithme : il suffit deffectuer un parcours du fichier f et de
ranger dans le fichier g chaque lment de f.
Len-tte est : void copie(FICHIER *f, FICHIER *g) ;
// spcification ()(g = f)
Raisonnement par rcurrence :

Rakotoasimbahoaka Cyprien

Hypothse : g = f f+ = <>
g =f
Robert
anne 2008
f+ <>
lire (f, c) ;
g = f-, c = Df-

*
*

38

Algorithmes et programmation structure

Lalgorithme est alors :


programme ch3_8.c
3.4.1.1. Somme ou concatnation de deux fichiers
A partir de deux fichiers f et g, on veut construire un
fichier h tel que : h = f || g. Cest--dire que si f=<x1,
x2,,xn> ; g=<y1, y2,,yn> alors, on obtient h=<x1,
x2,,xn, y1, y2,,yn>
Lalgorithme consiste copier f dans h, puis complter
par les lment de g. Lalgorithme est :
programme ch39_9.c
3.4.1.2. Eclatement dun fichier en plusieurs
On veut construire m fichiers squentiels (g1, g2,
g3,,gm) partir dun seul fichier squentiel f en utilisant
un critre dclatement. On appelle aussi ventilation dun
fichier.
a).Eclatement dun fichier en deux fichiers suivant le
critre de parit.
Le fichier est compos de valeurs simples entires. La
fonction boolenne appele pair dtermine la parit dun
lment du fichier. Elle possde un paramtre donn x
qui est un nombre entier ; elle dlivre vrai si x est un
nombre pair, sinon elle dlivre faux.
On va construire deux fichiers fpair contient les nombres
pairs et fimpair contient les nombres impairs. Le fichier f
de donnes est le fichier pilote.
Eexmple:si f=<2, 3, 1, 6, 8, 5, 4>, alors fpair=<2,6, 8, 4>
et fimpair = <3, 1, 5>.
Len-tte est :
void pairimpair (FICHIER *f, FICHIER *pair, FICHIER
*impair)
// spcification ( )(pair contient les valeurs paires de f,
// fimpair contient les valeurs impaires de f)

Raisonnement par rcurrence :


Hypothse :
fpair contient les valeurs paires de f-,
fimpair contient les valeurs impaires de f f+ = <>

fpair contient les valeurs paires de f,


fimpair contient les valeurs impaires de f. *

f+ <>

lire (f, c) ;
>> pair(c)

crire(fpair, c) ;
>> pair(c)

crire (fimpair, c) ; H
Itration : tantque(non fdf(f))
Initialisation : ouvrir (f, en lecture);
ouvrir (fpair, en criture) ;
ouvrir (fimpair, en criture)
programme ch3_10.c

b). Eclatement dun fichier en deux fichiers suivant le rang


de llment.
Eclater un fichier f en deux fichiers de telle sorte que tous les
lments de rang pair soient rangs dans le fichier f2 et les
lments de rang impair dans le fichier f1.
Exemple : si f=<2, 3, 1, 6, 8, 5, 4>, alors f1=<2, 1, 8, 4>, f2 =
<3, 6, 5>.
Len-tte est :
void rpairimpair (FICHIER *f, FICHIER *f1, FICHIER * f2)
// spcification ()(f1 contient les lments de // // // rang
impair de f, f2 les lments de rang pair de f)
Algorithme : il suffit chaque itration de ranger deffectuer
deux lectures et de ranger le premier lment dans f1 et le
second dans f2. Pour la deuxime lecture, on doit sassurer que
llment bien en se protgeant par le prdicat fdf.
Raisonnement par rcurrence.
Hypothse :
f1 contient les lments de rang pair de f-,
f2 contient les lments de rang impair de f-, f-=f12p
f+ = <>
f1 contient les lments de rang impair de f,
f2 contient les lments de rang pair de f. *
f+ <>
lire (f, c) ;=> c=x2p+1=> crire(f1,c)H
>> f+=<>
*
>> f+<>
lire(f, c) => c=x2p+2
crire (f2, c) ;
H
Itration : tantque(non fdf(f))
Initialisation : ouvrir (f, en lecture);
ouvrir (f1, en criture) ;
ouvrir (f2, en criture) H
Lalgorithme est :
Programme ch3_11.c
3.4.2. Algorithme de mise jour dun fichier.
Il sagit dinsrer ou de supprimer des lments dans un fichier.
Dans un but de simplicit, on supposera que la mise jour ne
porte que sur un seul lment.
3.4.2.1. Insertion dun lment dans un fichier.
a) Aucun critre nest donn.
On dispose din fichier f, dune valeur valinsert que lon
dsire ajouter au fichier f. On a deux possibilits : soit ajouter
llment en tte du fichier, soit lajouter en fin du fichier. Le
rsultat :
Soit : <valinsert> || f,
Soit : f || <valinsert>.
Dans le premier cas, il faut toujours crer un autre fichier
Programme ch3_12.c
Dans le deuxime cas, on cre dabord un autre fichier par
copie du fichier f ; puis on ajoute la valeur valinsert la fin. On
obtient alors :
Programme ch3_13.c
b) insertion par position.
On donne la place k du nouvel lment valinsert. Il sagit donc
dcrire un algorithme dinsertion la kime place de llment
valinsert dans le fichier f dont len-tte est :
void insertk( FICHIER *f, entier k, t valinsert, FICHIER *g,
entier * possible)
//spcification (k>0)((possible, g=f1k-1||<valinsert>||fkn) //v
(possible, g indfini))
Raisonnement : on construit un fichier g rsultant de la
concatnation des trois sous-fichiers :
g = f1k-1 || <valinsert> || fkn

Rakotoasimbahoaka Cyprien Robert

anne 2008

39

Algorithmes et programmation structure


Lalgorithme se dcompose en trois parties :

Copie des k-1 premiers lments de f,

Ajout de llment valinsert,

Copie des n-k+1 derniers lments de f.


Si k[1..n+1], on obtient bien le fichier cherch. On peut
noter que si k = 1, f1k-1 est vide et que si k = n+1, fkn est
vide. On a suppos k > 0. Si k > n+1, le problme de
linsertion na plus de sens et il faut signaler cette
impossibilit dans le rsultat de lalgorithme. On utilise
une variable boolenne possible qui prendra la valeur vrai
ou faux suivant que linsertion a t ou non ralise.
Le dbut de lalgorithme :
i = 1 ; ouvrir (f, en lecture) ; ouvrir (g, en criture) ;
tantque (non fdf(f) et (i < k)){ lire (f, c) ;
crire (g, c) ; i += 1 ; }
A la sortie du tantque, on a : fdf(f) v i k
Avec k > 0, i k i = k
Tableau 5 : Tableau de sortie
i=k
fdf(f)
Rsultat
vrai
vrai
insertion
vrai
faux
insertion et copie du reste de f
faux
vrai
pas dinsertion
faux
faux
impossible (tantque)
Lalgorithme complet est :
Programme ch3_14.c
c) insertion aprs une valeur.
On veut insrer la valeur valinsert aprs ou avant (on
choisit aprs) la valeur val dans le fichier f. Len-tte est :
void inserv(FICHIER *f, t val, t valinsert, FICHIER *g,
entier * possible)
// Spcification(f<>)((possible,g=f||<valinsert> //
||f,f=f||f,f=f||<val>, valf) v (possible,
// g = indfini))
Dans le cas o il y a plusieurs exemplaires de la valeur
val, on insrera aprs la premire occurrence de cette
valeur. On peut donc dire que le fichier rsultat g est la
concatnation de trois fichiers f, <valinsert>, f, o f
dsigne les premiers lments de f jusqu la rencontre de
la valeur val qui sera la dernire de f. En dautres
termes :
f=f||f, f=f||<val>, donc val = Df, valf.
Linsertion est impossible dans le cas o la valeur val est
absente du fichier f.
Construction de g = f.
Raisonnement par rcurrence
Hypothse : val f-, g = f-, c = Df c = val

la construction de f- est termine

c val

val f-, g = f-, c = Df>> f+ = <>


val f
>> f+ <>
lire (f, c) ;
val f-, g=f-, c=DfLalgorithme
est :
crire(g, c)complet
;=> g = f-

Programme
ch3_15.c
Itration : tantque(non
fdf(f)et(cval))
insertion
dans un fichier tri.
Initialisation : d)
ouvrir
(f, en lecture);
en criture)
lire(f, c) ; dans
Onouvrir
veut(g,ajouter
un ;lment

un fichier tri f de
sorte
valf-, que
g=f-, c=Dftelle
lon obtienne un fichier tri g.
crire(g,
c) ;
H
Lajout
est toujours
possible.
Exemple : f = <c, f, g, m>.
insertion de a <a, c, f, g, m>

insertion de h <c, f, g, h, m>

insertion de z <c, f, g, m, z>


insertion de f <c, f, f, g, m>
On considre que g est la concatnation de trois sous-fichiers :
g = f || <valinsert> || f
avec f = f || f, f< valinsert f.
Cas particuliers :

(f = <>), (f <>) : valinsert f,

(f <>), (f = <>) : f < valinsert,

(f = <>), (f = <>) : g = <valinsert>,


Dautre f et f sont tris, lalgorithme peut tre dcompos en
trois parties :

Copier tous les lments de f infrieurs valinsert,

Insrer llment valinsert,

Copier le reste des lments de f.


Copier tous les lments de f infrieurs valinsert
Raisonnement par rcurrence
Hypothse : g = f--, f-- < valinsert, ftri, c = Df f+ = <>
>> c <valinsert
crire(g, c) ;
Premire partie termine
>> c valinsert
premire partie termine
f+ <>
>> c < valinsert
crire(g, c) ; lire(f, c) ;
>> c valinsert
premire partie termine

*
*

H
*

Itration : tantque(non fdf(f)et(cval))


Initialisation: ouvrir (f, en lecture); ouvrir (g, en criture);
f+ = <>

crire(g, valinsert) ;
f+ <>

lire(f, c)

Le dbut de lalgorithme :
{tc;
ouvrir (f, en lecture) ; ouvrir(g, en criture) ;
si(fdf(f)) crire(g, valinsert) ;
sinon
{ lire(f, c) ;
tantque(non fdf(f) et (c < valinsert)){
crire(g, c) ; lire(f, c) ;
}
// fdf(f) v c valinsert
}
}
Tableau 6 : tableau de sortie

fdf(f)
vrai
vrai
faux

c valinsert
vrai
faux
vrai

faux

faux

Rsultat
crire(g,valinsert) ; crire(g,c) ;
crire(g,c) ; crire(g,valinsert) ;
crire(g,valinsert) ; crire(g,c) ;
copier le reste de f
impossible (tantque)

Lalgorithme complet est alors

Programme ch3_16.c
3.4.2.2. Suppression dun lment dans un fichier
On peut supprimer le kime lment (suppression par position)
ou supprimer une valeur (suppression associative). Dans le cas
dune suppression associative le fichier peut tre tri, ce qui
permet d
acclrer lalgorithme au cas o llment que lon veut
supprimer est absent du fichier.

Rakotoasimbahoaka Cyprien Robert

anne 2008

40

Algorithmes et programmation structure


a) Suppression par position
On veut supprimer le kime lment du fichier f. Len-tte
est :
void supprimek(FICHIER*f, entier k, FICHIER*g, entier
*possible)
//spcification ( ) (possible, f1k-1|| fk+1n)v(possible, g
indfini)
On considre que lon construit un fichier g qui soit la
concatnation de deux sous-fichiers :
g = f1k-1 || fk+1n
Lalgorithme se dcompose en trois parties :

Copie des k-1 premiers lments de f,

Lecture du kime lment (sans copie),

Copie des n-k derniers lments de f.


Cas particuliers :

Si k = 1, le fichier f1k-1 est vide,

Si k = n, le fichier fk+1n est vide.


La suppression nest possible que si 1kn. Si k0 ou
k>n, la suppression est impossible (le kime lment
nexiste pas). Une variable boolenne possible permet
de savoir si lalgorithme a pu ou non supprimer le kime
lment.
Copie des k-1 premiers lments de f.
Le dbut de lalgorithme est le suivant :
ouvrir(f, en lecture) ;
i = 1 ; ouvrir (g, en criture) ;
tantque(non fdf(f) et (i < k)){ lire(f, c) ;
crire (g, c) ; i += 1 ;
}
Tableau 7 : tableau de sortie
fdf(f) i k
Rsultat
vrai
vrai
possible = faux
vrai
faux
possible = faux
faux
vrai
suppression si i = k
faux
faux
impossible (tantque)
1re ligne : fdf(f), i k

i > k, conduit k 0, donc la suppression est impossible dans ce cas.

i = k, fdf(f), g=f-, f-=f1k-1, f+ =<>, on a bien trouv


ime
place qui correspond la fin du fichier. Le kime
la k
lment nexiste pas et on ne peut pas le supprimer. Cest
le cas o k = n +1
2ime ligne : i < k, fdf(f)

On a parcouru tous les lments du fichier sans


trouver le kime lment. Cest le cas o k > n+1. La suppression est impossible.
3ime ligne : i k, fdf(f)

i > k, k0 donc suppression impossible.

i = k, fdf(f) g=f1k-1, f-=f1k-1, f+<>, le kime lment


existe, on peut donc le supprimer.
4ime ligne : fdf(f), i < k

fdf(f) v (ik) nest pas une assertion.


A la sortie du tantque, le test i = k est insuffisant car il
rpond vrai aux 1reet 3imelignes. Il faut donc utiliser le
test : (i = k) et non fdf(f)
Dans ce cas l, on a :
(fdf(f), i=k, g=f1i-1)(g=f1k-1, fdf(f))
Lalgorithme complet est :
Programme ch3_17.c
b) Suppression associative
Nous nous limitons au cas de la suppression de la
premire occurrence de la valeur val.
Raisonnement : le fichier g est la concatnation de deux
fichiers f et f tels que :
f = f || <val> || f, val f

La suppression nest possible que si val f. On dfinit donc,


une variable possible qui indiquera si la suppression a t
effectue ou non.
Len-tte est le suivant :
void supprime(FICHIER *f, t val, FICHIER *g, entier
*possible)
Copie de f dans le fichier g :
f = f--, f- = f-- || <val>, val f
Raisonnement par rcurrence
Hypothse : g = f--, val f--, c = Df c = val

premire partie termine : val = Df- *


c val
>> f = <>

val f

premire partie termine


>> f <>

crire(g, c) ;
val g, g = f-, c = Df-

lire(f, c) ;
H
Itration : tantque(non fdf(f)et(cval))
Initialisation: ouvrir (f, en lecture); ouvrir (g, en criture);

val g, g = f-;
lire(f, c)

Le dbut de lalgorithme est le suivant :


{ ouvrir(f, en lecture) ; ouvrir (g, en criture) ;
possible = 0 ; lire (f, c) ;
tantque(non fdf(f) et (cval)){ crire(g, c) ;
lire (f, c) ;
}
// fdf(f) v (c = val)
Tableau 8 : tableau de sortie
fdf(f)
vrai
faux
vrai

c = val
vrai
faux
vrai

faux

faux

rsultat
val = Df, g=f ; possible = 1
val f ; possible = 0 ;
possible = 1; suppression de val
copie du reste de f
impossible (tantque)

1re ligne : fdf(f), c = val


val est le dernier lment de f. On donne possible la valeur 1
et lalgorithme est termin.
2ime ligne : fdf(f), c val
Tous les lments du fichier f ont t parcourus sans trouver de
valeur val. La suppression est donc impossible
3ime ligne : fdf(f), c = val
On a trouv une valeur val f (val=c) et telle que val f--,
cest donc bien la premire occurrence que lon peut supprimer.
Ensuite on copie le reste de f.
4ime ligne : fdf(f), c val
fdf(f) v trouve nest pas une assertion.
Poursuite de lalgorithme : il faut tester la valeur de
lexpression c = val.
Lalgorithme complet est alors le suivant :
Programme ch3_18.c
c) Suppression associative dans un fichier tri.
Afin de simplifier lalgorithme, on supposera que le fichier f
tri est non vide. Comme f est tri, il peut tre dcompos en f
et f tels que :
f = f || f, f < val f.

Rakotoasimbahoaka Cyprien Robert

anne 2008

41

Algorithmes et programmation structure


la premire partie de lalgorithme sonsiste copier dans g
les lments de f infrieurs val. Ensuite, si la valeur
val est prsente, on la supprime et on copie le rest de f.
Construction de g = fRaisonnement par rcurrence.
Hypothse : g = f-, f- < val, c = Df c val
Df- val
Premire partie termine
*
c < val
>> f+ = <>
val f
premire partie termine
*
>> f+ <>
crire(g, c) ;
g < val, g = f-, c = Df lire(f, c) ;
H
Itration : tantque(non fdf(f)et(c<val))
Initialisation: ouvrir (f, en lecture); ouvrir (g, en criture);
lire(f, c)
H

fdf(f)
vrai
vrai
faux

faux

Algorithme : suppression associative dun fichier tri


Programme ch3_19.c
Tableau 9 : tableau de sortie.
rsultat
c val
vrai
*f--<val,c=Df=val=>possible=1;termin
*f--<val,c>val=>possible=0 ; termin
faux
=>possible=0 ; (val<f) termin
vrai
*c=val=>^possible=1 ;
=>supprimer puis recopier le reste de f
*c>val=>possible=0 ; termin
faux
impossible (tantque)
4. Rcursivit et structures de donnes avances.
Cette deuxime partie est la suite logique du premier.
En particulier, nous utilisons les mmes mthodes et les
notations que Il sagit de donner une bonne initiation la
programmation rcursive et de construire des algorithmes
classique et fondamentaux sur des structures de donnes
plus avances telles que les listes chanes, les piles, les
files dattente, les tables et les arbres.
4.1. Listes linaires chanes.
4.1.1. Dfinition.
Une cellule : un couple compos dune information et
dune adresse. Linformation pourra tre simple ou
structure. Une cellule est connue par son adresse.
Cel
information
adresse
CELLULE
Une liste linaire chane ou simplement une liste chane
est constitue dun ensemble de cellules chanes entre
elles. Cest ladresse de la premire de ces cellules qui
dtermine la liste. Cette adresse se trouve dans une
variable que nous appellerons souvent liste.
Par convention, on notera liste+ la suite des lments
contenus dans la liste dont ladresse de la premire
cellule se trouve dans la variable liste.

Exemple : la liste linaire (a, b, c, d) est schmatis


liste

A
b
c
et liste+ = (a, b, c, d). On notera :

- que, si liste = nil, liste+ est vide (liste+=<>),


- quil y a autant de cellules que dlments,
- que le champ suivant dune cellule contient l adresse
de la cellule suivante,
-que le champ suivant de la dernire cellule contient la
valeur nil.
- quil suffit de connatre ladresse de la premire cellule
range dans la variable liste pour avoir accs tous les
lments en utilisant les notations :
liste->info, liste->suivant, liste->info->suivant, .
liste->info et liste->suivant->info ne sont dfinie que si
liste est diffrent de nil.
Notation : on utilisera les mmes notations que dans les
chapitres prcdents. Par exemple: a<liste+
indique que a est infrieur tous les lments de liste+.
Sous-liste : une sous-liste p+ de liste+ est une liste telle
que les lments de p+ soient une suite dlments
conscutifs de liste+.
Exemple : liste+ = (a, b, c, d, e).
p+ = (b, c) est une sous-liste de liste+.
p+ = (b, d) nest unes sous-liste de liste+.
Soient une liste liste+ et une sous-liste p+ de liste+
reprsente ainsi :
liste
p

On peut dfinir les notations suivantes :


p-liste = (a, b), p+ = (c, d).
dans le cas o p-liste nest pas ambigu on utilise la
notation p-.
On notera que : liste+ = p- || p+,
On remarque que si liste+ = (a, b, c, d), liste- = <> et
que si liste = nil on a liste+ = <>.
liste1
p

liste2
p- est ambigu car on ne sait pas si cest
p-liste1 = (a, b) ou p-liste2 = (a, b).
4.1.2. Algorithme de cration dune liste chane.
Crer une liste chane qui est la reprsentation de (a, b).
Dclaration : type structure.
structure cellule { t info ;
structure cellule * suivant ;
};
O t est un type simple, vecteur, structure,et on peut dclarer
une variable liste :
structure cellule*liste; //liste est de type structure cellule* ou
bien pour viter dcrire chaque fois le type structure cellule
*, on dfinit dabord un type synonyme de structure cellule * :
type structure cellule *pointeur ; /* pointeur est un type
synonyme de structure cellule *. */
On peut dclarer une variable de type pointeur :
pointeur liste, p ; /* p, liste sont de type pointeur. Ce type
pointeur sera utilis dans la suite du cours.

Rakotoasimbahoaka Cyprien Robert

anne 2008

42

Algorithmes et programmation structure


Ainsi la variable p peut tre reprsente par le
schma :
p

p->
<-------------
info

suivant

Ladresse de la cellule est range dans la variable p. On


dira, cellule dadresse p ou cellule pointe par p. La
cellule contient deux champs : le champ de nom info
contenant une information et le champ de nom suivant
contenant une adresse.
Si p ne contient pas la valeur nil (pnil), p->info permet
daccder linformation de la cellule dadresse p et p>suivant permet daccder l adresse contenue dans la
cellule dadresse p.
Pour de raisons de facilit, nous allons crer la liste
partir de son dernier lment.
Etape 1 : cration dune liste vide dadresse liste.
liste = nil ;
Etape 2 : cration de la liste dadresse liste et contenant
linformation b.
- cration dune cellule dadresse p contenant l
information b :
p =(pointeur)allocation(taille(pointeur)) ;
p->info = b ;
- chanage avec la liste prcdente :
p->suivant =liste ;
cration de la liste dadresse liste reprsentation de (a, b)
:
liste = p ;
On peut gnraliser lalgorithme en supposant que les
lments successifs se trouvent dans un fichier f. Dans ce
cas, on cre la liste partir de son dernier lment et du
dernier lment du fichier f. On obtient alors une liste
contenant les lments de f rangs dans lordre inverse.
Algorithme:cration dune liste partir dun fichier.
Programme ch4_1.c
Passage dun vecteur une liste chane : partir des
lments du vecteur v[i], on cre la liste partir de son
dernier lment et du dernier lment du vecteur. On
obtient ainsi les lments dans le mme ordre.
Algorithme :
Programme ch4_2.c
Pour obtenir les lments du fichier dans le mme ordre,
on doit crer la liste partir de son premier lment.
Pour ce faire, on doit dabord prvoir le cas du premier
lment qui permet la cration de la premire cellule de la
liste et dont ladresse doit tre prserve car elle
permettra laccs toutes les cellules cres
Ensuite pour chaque lment de f, on doit crer une
nouvelle cellule quil faudra insrer en fin de liste et non
plus en tte.
Algorithme :
Programme ch4_3.c
4.1.3. Parcours dune liste.
a) schma rcursif.
Pour lcriture des algorithmes, sous-forme rcursive, on
utilise la dfinition suivante dune liste chane :
Une liste chane est :

Soit une liste vide (liste = nil),

Soit compose dune cellule (la premire) chane


une sous-liste (obtenue aprs suppression de la premire
cellule).

Exemple : (a, b, c, d, e) est compose dune cellule contenant a


et dune sous-liste contenant (b, c, d, e). Cette sous-liste a pour
adresse liste->suivant+. On peut alors construire deux
parcours :
Premier parcours
- on traite la premire cellule,
- on effectue le parcours de la sous-liste liste->suivant +.
Algorithme: parcours dune liste lendroit.
Programme ch4_4.c
N.B. La variable liste est une donne. Seul son contenu est
protg, cest--dire ladresse de la premire cellule qui est le
point dentre dans la liste. Les autres informations ne sont pas
protges.
Deuxime parcours
- on effectue le parcours de la sous-liste liste->suivant +.
- on traite la premire cellule.
Algorithme : parcours de la liste lenvers.
Programme ch4_5.c
Exemple : soit liste+ = (a, b, c, d). Dans le cas de lexcution de
linstruction parcours1 ( liste ), on obtient
parcours1 ((a, b, c, d)) :
traiter(a)
parcours1 ((b, c, d)) dont lappel permet dexcuter
traiter (b)
parcours1((c, d))dont lappel permet dexcuter
traiter (c)
parcours1((d)) dont lappel permet dexcuter
traiter (d)
parcours1(()) lalgorithme est termin.
On constate que lon traite les lments dans lordre
Dans le cas de lexcution de laction parcours2, on obtient :
parcours2 ((a, b, c, d)) qui conduit lexcution de :
parcours2 (b, c, d) ;
suivi de traiter (a) ;
Il faut donc effectuer parcours2 ((b, c, d)) avant dexcuter
traiter (a). On dit que laction traiter (a) est suspendue ; elle
sera active quand lexcution de laction parcours2 (b, c, d)
sera compltement termine.
parcours2 ((b, c, d)) conduit lexcution de :
parcours2 ((c, d))
suivi de traiter (b)
Laction traiter (b) ne sera effectue que lorsque lexcution de
laction parcours2 (c,d) sera termine
parcours2 ((c, d)) conduit lexcution de :
parcours2 ((d))
suivi de traiter (c)
Laction traiter (c) ne sera effectue que lorsque lexcution de
laction parcours2 ((d)) sera termine
parcours2 ((d)) conduit lexcution de :
parcours2 (())
suivi de traiter (d)
Lexcution de laction parcours2(()) est termine, on excute
alors laction traiter (d)
Lexcution de laction parcours2 ((d)) tant ter-min, on
excute maintenant traiter(c).
Lexcution de laction parcours2((c, d)) tant alors termine,
on excute maintenant traiter (b)
Lexcution de laction parcours2 ((b, c, d)) tant maintenant
termine, on excute traiter(a).
Lexcution de laction parcours2 ((a, b, c, d)) tant ter-mine,
lalgorithme lest aussi.
On constate que les lments sont excuts dans lordre
inverse.
b) Schma itratif. Le deuxime parcours nest pas simple
obtenir en itratif. Dans le cas gnral, il est ncessaire de
disposer dune pile, comme nous le verrons dans les chapitres

Rakotoasimbahoaka Cyprien Robert

anne 2008

43

Algorithmes et programmation structure


suivants. Nous nous limitons, pour le moment, au premier
parcours dont le schma itratif est :
Algorithme: schma itratif du premier parcours
Programme ch4_6.c
Le paramtre liste tant un paramtre donn, ladresse de
la premire cellule est protge. Dans le cas o le
paramtre serait un paramtre rsultat, il serait ncessaire
dutiliser une variable auxiliaire de type pointeur pour
effectuer le parcours afin de ne pas perdre laccs la
liste.
Algorithme : schma itratif de parcours1, protection de
ladresse de la premire cellule.
Programme ch4_7.c
4.1.4. Algorithmes dcriture des lments dune liste.
On se propose dcrire sous forme rcursive deux
algorithmes dcriture des lments dune liste.
a) premire version.
On utilise le premier parcours parcours1. On crit donc
les lments de la liste partir du premier lment.
Algorithme : criture des lments de la liste lendroit.
Programme ch4_8.c
b) deuxime version.
On utilise le deuxime parcours parcours2 qui permet
dobtenir lcriture des lments partir du dernier
lment.
Algorithme : criture des lments lenvers.
Programme ch4_9.c
4.1.5. Exemples dalgorithmes sur listes chanes
4.1.5.1. Algorithme de calcul de la longueur dune
liste.
- schma itratif
Raisonnement par rcurrence
Hypothse : n = long (p-), o long dsigne le nombre
dlments de la liste p-.
p+ = <>
la liste possde n lments
lalgorithme est termin
*
p+ <>
la liste possde au moins un lment que
lon peut dnombrer.
n += 1 ; p = p->suivant ; H
Itration : tantque (liste nil)
Initialisation: il suffit que la variable p contienne ladresse de
la premire cellule de la liste (cette initialisa
Tion est ralise par le passage par donne de liste) et d
Initialiser n zro :
n=0;
H

Algorithme : nombre dlment dune liste


Programme ch4_10.c
b) schma rcursif
Raisonnement :

liste+ = <>
sa longueur est alors gale zro.
retour 0 ; termin
*
liste+ <>
elle est donc compose dune cellule (le
premier lment) chane la sous-liste liste->suivant+. La
longueur de la liste est donc gale un plus la longueur de la liste
liste->suivant+.
retour (1 + long (liste->suivant)); H
Algorithme : nombre dlment en algorithme rcursif.
Programme ch4_11.c

4.1.5.2. Algorithme de calcul du nombre doccurrences dun


lment dans une liste.
Mme raisonnement que dans la cas particulier dun fichier squentiel.
a) schma itratif (hypothse val p-)
Algorithme : nombre doccurrences dun lment dans la liste, schma
itratif.
Programme ch4_12.c
b) schma rcursif.
Raisonnement

liste+ = <>

nombre doccurrences est gale zro.


retour 0 ;

liste+ <>

elle est donc compose dun lment et dune sousliste liste->suivant+.


>> liste->info = val
le nombre doccurrences est gal un
plus le nombre doccurrences de val dans la sous-liste liste->suivant+.
retour(1+nboc(liste->suivant, val)); H
>> liste->info val

le premier lment ne contient pas la


valeur val, le nombre doccurrences de val dans la liste est donc gal
au nombre doccurrences de val dans la sous-liste liste->suivant+.

retour (nboc (liste->suivant, val));

On notera quil faut toujours tester dabord la liste vide afin quon
puisse ensuite, dans le cas contraire, utiliser les notations liste->info et
liste->suivant (qui ne sont dfinies que si liste nil).
Algorithme : nombre doccurrences dun lment dans une liste,
schma rcursif.
Programme ch4_13.c
4.1.5.3. Algorithmes daccs dans une liste.
On distingue deux sortes daccs: accs par position ou accs
associatif.
a) Algorithme daccs par position
- schma itratif
On utilise le mme algorithme que celui donn sur les fichiers
squentiels.
Algorithme : accs par position un lment dans une liste.
Programme ch4_14.c
- schma rcursif
Le raisonnement est fond sur la constatation suivante : chercher le
kime (k>1) lment revient chercher le k-1ime lment dans liste>suivant+ comme indiqu dans le schma suivant :
liste

(1)

(2)

(k-1) (k)

(n)

liste->suivant
(1)

(k-2)

(k-1)

(n-1)

Le raisonnement est :

liste+ = <>

Algorithme est termin, le kime lment n


existe pas et pointk prend la valeur nil.
retour liste ;

liste+ <>
>> k = 1

Algorithme est termin et pointk prend la


valeur de ladresse contenue dans la variable liste

retour liste ;.*

>> k 1

On rappelle la fonction pour chercher le


k-1ime lment dans la sous-liste liste->suivant+.

Rakotoasimbahoaka Cyprien Robert

retour (pointk (liste->suivant, k-1)) ;

anne 2008

44

Algorithmes et programmation structure

On remarque que pour k=1 et liste=nil, la pointk retourne


la mme valeur : celle contenue dans la variable liste. On
peut donc relier ces deux conditions par un connecteur ou
car elles sont indpendantes lune de lautre, er raliser
ainsi une mise en facteur de laction :
pointk = liste ;
Algorithme : accs par position, schma rcursif
Programme ch4_15.c
b) Accs associatif dans une liste
- schma itratif
On souhaite crire une fonction dont len-tte est :
vide accesv (pointeur liste, t val, pointeur *point, entier
*acces)
/*spcification()((point=adresse de la
premire
occurrence de val, val liste+) v (point=nil, val
liste+))*/
Raisonnement par rcurrence
Hypothse : val p-.
p+ = <>

lalgorithme est termin, la valeur contenue

dans val nest pas prsente dans la liste*


p+ <>
>>p->info=val

lalgorithme est termin ; la valeur


contenue dans val est prsente dans la liste.
>>p->infoval

p=p->suivant ; H

Itration : tantque ((p nil) et (p->info val))On rappelle que p>info nest dfinie que si pnil. On utilise une variable boolenne
trouve.
Initialisation: trouve = faux ;

Algorithme : accs par position, schma itratif.


Programme ch4_16.c
-schma rcursif
En utilisant une convention ci-aprs, on peut crire cet
algorithme sous forme dune fonction rcursive.
pointeur point (pointeur liste, t val)
//spcification () ((point = adresse de la premire
//occurrence de val, val liste+)v(point = nil, val
//liste )).
Convention :

point devra contenir ladresse de la cellule contenant la valeur de la premire occurrence de la valeur val
si elle existe dans liste+,

point devra contenir la valeur nil si la valeur val


nexiste pas dans liste+.
Le raisonnement
:
liste+
= <>

Algorithme est termin, point dlivre la


valeur nil (val liste+).
retour nil ;
*
liste+ <>
>> liste->info = val
Algorithme est termin et point dlivre la
valeur contenue dans la variable liste.
retour liste ;.*
>> liste-> val
On recherche la prsence de val dans la sousliste liste->suivant+.
retour (point (liste->suivant, k-1)) ;

Algorithme : accs par valeur, schma rcursive.


Programme ch4_17.c
On notera quil est impossible de mettre en facteur laction
retour liste ; cause des risques lincohrence dus aux
conditions liste==nil et liste->info qui ne sont pas
indpendantes.
c) Accs associatif dans une liste trie.
- dfinition dune liste trie.
* une liste vide est trie,
* une liste dun lment est trie,
* une liste de plus dun lment est trie si tous les lments
conscutifs vrifient la relation dordre :
liste nil, liste->suivant nil, liste->info liste->info->
suivant.
-schma rcursif
On veut crire une fonction dont len-tte est :
pointeur fonction point (pointeur liste, t val)
// spcification (liste+ est trie) ((point = adresse de la //
premire occurrence de val, val liste) v (point = liste, // val
liste+)).
Le raisonnement :

liste+ = <>
la valeur val nest pas prsente dans liste+
retour nil ;.*
liste+ <>
>> liste->info < val
on doit chercher la premire occurrence de val
dans liste->suivant+.
retour point (liste->suivant, val)
>>liste->info > val
la valeur val nest pas dans la liste
retour nil ;*
>> liste-> info == val
le cellule dadresse liste contient la premire
occurrence de val.
retour liste ;..*
Algorithme : accs associatif dans une liste trie, schma
rcursif.
Programme ch4_18.c
d) Algorithme de recherche dune sous-liste dans une liste.
On recherche un ensemble de valeurs dans une liste. On peut
formaliser le problme comme suit :
Soient :

une liste p+ note (a1, a2, , an),

une sous-liste sp+ note (b1, b2,, bp).


Rechercher la sous-liste sp+ dans la liste p+ revient chercher
un i tel que : 1 i n-p+1,
ai+k-1 = bk k [1..p]
On admettra que la sous-liste nest jamais vide. On peut
galement dire que p+ est la concatnation de trois sous-listes :
p+ = la+ || sp+ || lb+. Dans le cas o la+ est vide on dit que sp+
est un prfixe de p+. De mme, si on appelle lc+ la liste
compose de sp+ et de lb+ (lc+ = sp+ || lb+), on dit que sp+ est
un prfixe de lc+.
Rechercher la sous-liste sp+ dans p+ revient chercher si
sp+ est un prfixe de p+.
Supposons que nous disposons de la fonction prefixe dont lentte est :
entier prefixe (pointeur liste, pointeur sliste)
//spcification (slistenil) (prefixe=sliste+ est un //prfixe
de liste+).
Exemple : (a, b, c) est un prfixe de (a, b, c, d, e).

Rakotoasimbahoaka Cyprien Robert

anne 2008

45

Algorithmes et programmation structure


(a, c) nest pas un prfixe de (a, b, c, d, e).
Par convention, on dira que toute liste est un prfixe
delle-mme. Une liste vide est un prfixe de nimporte
quelle liste.
On crira cette fonction plus tard.
a) schma itratif
Raisonnement par rcurrence de la recherche dune
sous-liste.
Hypothse : sliste+ p-.
p+ = <>

lalgorithme est termin, la fonction dlivre

la valeur faux car sliste+ nest pas incluse dans


liste+*
p+ <>
>>sliste+ est un prfixe de p+

lalgorithme est termin ; la fonction


dlivre vrai car sliste+ est incluse dans liste+.
>>sliste+ nest pas un prfixe de p+

p=p->suivant ; H
Itration : tantque ((non prefixe(p, sliste)) et (p nil))
Initialisation : il suffit de commencer au dbut de la liste H
Algorithme : recherche dune sous-liste dans une liste
Programme ch4_19.c
b) schma rcursif
On souhaite crire une fonction dont len-tte suit :
entier recherchesliste (pointeur liste, pointeur sliste)
//spcification(sliste+ nil)(recherchesliste = (liste+ =
//la+ || sliste+ || lb+))
Le raisonnement :

Algorithme : recherche dune sous-liste dans une liste, schma


itratif.
Programme ch4_21.c
Daprs le raisonnement par rcurrence, la sortie de
litration, la fonction prefixe dlivre la valeur vrai (1) dans le
cas o sliste+ est vide et faux (0) dans le cas contraire.
On peut trouver ce rsultat par lanalyse du tableau de sortie
(tableau 10).
Tableau 10 : Tableau de sortie
liste=nil
sliste=nil
rsultat
egal
vrai
vrai
vrai
impossible
vrai
vrai
faux
vrai
vrai
faux
vrai
impossible
vrai
faux
faux
faux
faux
vrai
vrai
impossible
faux
vrai
faux
vrai
faux
faux
vrai
faux
faux
faux
faux
impossible
1re, 3me, 5me ligne
Impossible,car egal implique listenil et slistenil
8me ligne
Impossible cause du tantque,
car ((liste=nil) v (sliste ==nil) v (egal)) nest pas une
assertion.
2me ligne. Les deux sous-listes sont identiques ; sliste+ est
donc un prfixe de liste+.
4me ligne. Liste+ est un prfixe de sliste+ qui nest pas encore
termine, sliste+ nest donc pas un prfixe de liste+.
6me ligne. Sliste+ est un prfixe de liste+ qui nest pas encore
termine.
On constate que sliste = nil est la solution.
- schma rcursif. Le raisonnement :

liste+ = <>
sliste+ nest pas une sous-liste de liste+
.*
liste+ <>
>> sliste+ est un prfixe de liste+
sliste+ est une sous-liste de liste+.
..*
>>sliste+ nest pas un prfixe de liste+
On cherche si sliste+ est un prfixe de la liste
liste->suivant+.
retour retour recherchesliste(liste->sui-vant,
sliste) ;
Algorithme : recherche dune sous-liste dans une liste, schma
rcursif.
Programme ch4_20.c
c) criture de la fonction prefixe.
- schma itratif.
Il faut effectuer un parcours simultan de deux sous-listes en
comparant les lments situs la mme position.
Raisonnement par rcurrence :
Hypothse : p- == sp-.
sp+ = <>

sliste+ est un prfixe de liste+..*


sp+ <>
>>p+ = <>

sliste+ nest pas un prfixe de liste+..*


>>p+ <>
>>> p->info==sp->info

liste+ = <>

sliste+ nest pas une sous-liste de liste+

retour 0 ;.*
liste+ <>
>> liste->info sliste->info

sliste+ nest pas une sous-liste de liste+.

retour 0 ;....*
>>liste->info==sliste->info
>>>sliste->suivant == nil

sliste+ est une sous-liste de liste+.

retour 1 ; ..*
>>>sliste->suivant nil

retour prefixe (liste->suivant, sliste-> suivant) ;

Algorithme : recherche dune sous-liste dans une liste, schma


rcursif.
Programme ch4_22.c
4.1.6. Algorithmes de mise jour dans une liste.
Ces algorithmes ont une grande importance en raison de leur
facilit de mise en uvre. En effet, la mise en uvre dune liste
nentrane que la modification dun ou deux pointeurs sans
recopie ni dcalage des lments non concerns par la mise
jour.
4.1.6.1. Algorithmes dinsertion dans une liste.
a) Insertion dun lment en tte de liste.
Nous utilisons cet algorithme trs souvent pour raliser les
autres insertions. Cest un cas trs particulier car linsertion en
tte modifie ladresse de la liste.

p=p->suivant ; sp= sp->suivant ; H


>>> p->infosp->info

le premier lment de p+ et de sp+ sont


diffrents. sliste+ nest pas un prfixe de
p+.*
Itration : tantque ((p nil) et (sp nil) et (p->info == sp>info))Pour de raison de cohrence, on utilise une variable
boolenne egal
Rakotoasimbahoaka
Initialisation : il suffit de commencer au dbut de la liste
egal
= vrai ; H

Cyprien Robert

anne 2008

46

Algorithmes et programmation structure


Schma :
liste

Le raisonnement est :

liste ne contient quune seule cellule (liste-> suivant == nil)

(b)

(a)

cellule. retour liste*


liste contient plus dune cellule (liste->suivant nil)

lment insrer
p
Il faut dabord crer la cellule dadresse p. Ensuite, le
champ information reoit la valeur de llment, pour
terminer par la ralisation des deux liaisons (a) et (b) dans
cet ordre. Les lments suivants sont dcals
automatiquement dune position.
Algorithme : insertion dun lment en tte dune liste.
Programme ch4_23.c
b) Algorithme dinsertion dun lment en fin de liste.
- schma itratif.
Si la liste est vide, on est ramen une insertion en tte.
Dans le cas gnral, la liste nest pas vide.

liste

der

La liste contient ladresse de la dernire

retour dernier (liste->suivant)

Algorithme : dernire cellule de la liste, schma rcursif.


Programme ch4_27.c
- schma rcursif de inserfin.
On peut galement donner une version rcursive de la fonction inserfin
en utilisant la fonction insertete.
Le raisonnement :

liste+ = nil
On insre llment.
retour (insertete (*liste, elem)) ;*
liste nil)
retour inserfin ((*liste)->suivant, elem)

Algorithme : insrer un lment en fin dune liste, schma


rcursif.
Programme ch4_28.c
d) Algorithme dinsertion dun lment la kime place
Schma.

liste
(b)
lment insrer

(1)

(k-1)

(a)

(b)

p
Aprs avoir cr une cellule dadresse p contenant
linformation elem, on doit effectuer les liaisons (a) et
(b). Pour pouvoir effectuer la liaison (b), il faut connatre
ladresse der de la dernire cellule.
Disposant de la fonction dernier dont len-tte est :
pointeur dernier (pointeur liste)
//spcification (liste nil) (dernier = der, liste+ = //
der- || der+, der->suivant = nil).
Algorithme : insertion dun lment en fin de liste,
schma itratif.
Programme ch4_24.c
Algorithme : insertion en fin de liste, schma itratif 2.
Programme ch4_25.c
c) Ecriture de la fonction dernier.
- schma itratif.
On effectue un parcours de tous les lments de la liste en
prservant chaque fois ladresse de la cellule
prcdente.
Raisonnement par rcurrence.
Hypothse : precedent = Dp-.
O Dp- : adresse de la dernire cellule de p-.
p+ = <>

la fonction dlivre ladresse de la dernire

cellule de la liste.*
p+ <>

On passe llment suivant :

precedentque
= ples
; p=p->suivant
;dans
H linitialisation sont
On constate
deux actions

Itration : tantque (p nil)


celles excutes dans litration et quil est donc inutile
Initialisation : precedent = p ;
de les prvoir
linitialisation car on sait que litration
p = p->suivant
H

est au moins effectue une fois (la liste nest pas vide).
Algorithme : la fonction dernier
Programme ch4_26.c
- schma rcursif.

(k)
(k+1)

(n)
(n+1)

(a)
lment insrer
(p)

(k)

- schma itratif.
Linsertion dun lment la kime place consiste crer les
liaisons (a) et (b) dans cet ordre. Les lments suivants sont
automatiquement dcals dune position sans quon ait le
dplacer. Pour raliser la liaison (b), il faut connatre ladresse
de la cellule prcdente (la k-1me). Linsertion nest possible
que si k [1..n+1] o n est le nombre dlments de la liste. Il
faudra prvoir linsertion en tte (k==1) car elle modifie
ladresse de la liste. On utilisera la fonction pointk pour
dterminer ladresse de la k-1me cellule.
Algorithme : insertion dun lment la kime place, schma
itartif.
Programme ch4_29.c
Cet algorithme est qualifi ditratif bien quil ny ait pas
ditration visible. Celle-ci se trouve dans la version itrative
de la fonction pointk. On devrait plutt qualifier ce schma de
non rcursif.
Deuxime version : on peut galement effectuer le
raisonnement : insrer un lment la kime place revient
insrer cet lment en tte de la liste dont le pointeur de tte se
trouve dans le champ adresse de la k-1ime cellule (insertion en
tte de la liste qui commence la kime cellule) On peut
galement constater que lexcution des actions /*1*/, /*2*/,
/*3*/, /*4*/ de lalgorithme ci-dessus correspond lexcution
de laction insertete pour la liste precedent->suivant+ en
crivant la place de ces actions laction insertete
((*precedent)->suivant, elem) ;
- schma rcursif.

Rakotoasimbahoaka Cyprien Robert

anne 2008

47

Algorithmes et programmation structure

k=1
On effectue une insertion en tte de liste+
retour (insertete (*liste, elem)) ; ..*
k1
>>liste+ est vide
linsertion est impossible....*
>>liste+ nest vide
insertk ((*liste)->suivant, k-1, elem, *possible)

Algorithme : insertion la kime place, schma rcursif.


Programme ch4_30.c
e) Algorithme dinsertion de la valeur elem aprs la
premire occurrence de la valeur val.
Il suffit de connatre ladresse de la cellule qui contient la
premire occurrence de la valeur val pour pouvoir raliser
les liaisons (a), (b) dans cet ordre (schma).
premire occurrence
liste
de la valeur val

Cas particuliers :

liste+ = <>, il suffit dinsrer en tte de liste+.

la+ = <>, elem est donc infrieur ou gal la premire


valeur de la liste. On effectue une insertion en tte de liste+

lb+ = <>, elem est suprieur tous les lments de la liste.


On insre en fin de liste, donc en tte de la liste dont le point
dentre se trouve dans le champ suivant de la dernire cellule.
Lalgorithme consiste parcourir toute la liste la+ et insrer
elem en tte de la liste lb+, dont le point dentre se trouve
dans le champ suivant de la cellule dadresse dernier (la+).
- schma rcursif. : vide insertri(pointeur *liste, t elem) ;
Le raisonnement :

(b)
(a)
lment insrer
p
- schma non rcursif de la fonction point.
On utilise la fonction point pour connatre ladresse
de la cellule contenant la premire occurrence de la
valeur val. Ensuite, si cette valeur existe, il suffit
deffectuer une insertion en tte de la liste dont le
pointeur se trouve dans le champ adresse de la
cellule qui contient val.
Algorithme : insertion de elem aprs la premire
occurrence de val, schma non rcursif.
Programme ch4_31.c
- schma rcursif.
On souhaite crire la fonction insert sous-forme
rcursive
Le raisonnement :

liste+ = <>
linsertion est impossible car val liste+...*
liste <>
>>liste->info==val
on effectue linsertion en tte liste->suivant
insertete((*liste)->suivant, elem)..*
>>liste->infoval
insert(liste->suivant, val, elem)
Algorithme : insertion de elem aprs la premire
occur-rence de val, schma rcursif.
Programme ch4_32.c
f) Algorithme dinsertion dans une liste trie
On considre que la liste est la concatnation de
deux sous-listes la et lb telle : liste+ =la+||lb+ et
la+<elemlb+
Nous avons mis lgalit droite afin de minimiser
le temps de parcours.

liste+ = <>
on effectue linsertion en tte de liste+
insertete (*liste, elem)...*
liste <>
>>liste->info<elem
liste->info appartient la+
insertri ((*liste)->suivant, elem) ;
>>liste->infoelem
on est positionn sur le 1er lment de lb+.
insertete((*liste), elem) ; *

Algorithme : insertion dans une liste trie, schma rcursif.


Programme ch4_33.c
- schma itratif : il faut effectuer un parcours squentiel afin
de dterminer les listes la+ et lb+. On peut utiliser une variable
auxiliaire qui devra contenir, lors du parcours, ladresse de la
cellule prcdente. La variable preced contient la valeur de
ladresse de la cellule prcdente :

liste

preced

|______________________|
p- < elem, preced = DpHypothse : p- < elem, preced = Dp-.
O Dp- : adresse de la dernire cellule de p-.
p+ = <>
insrer en fin de liste (en tte de la liste
preced->suivant)
insertete(*(preced)->suivant, liste)*
p+ <>
>> p->info < elem
la cellule dadresse p appartient la+.
preced = p ; p=p->suivant ; H
>> p->info elem
on insre elem en tte de lb+.
insertete (preced->suivant, elem) ; *
Itration : tantque ((p nil) et (elem > (p->info))
Utiliser une variable boolenne : super.
Initialisation :
On a deux cas particuliers :
liste+ = <>, il faut effectuer une insertion en tte de
liste+ : insertete (*liste, elem) ;
liste+ <>, elem liste->info, on effectue une
insertion en tte de liste+ : insertete (*liste, elem) ;
Ces deux cas particuliers tant traits, on ralise
linitialisation preced = liste ;
p = liste->suivant
H

Rakotoasimbahoaka Cyprien Robert

anne 2008

48

Algorithmes et programmation structure


Algorithme : insertion dun lment dans une liste trie,
schma itratif.
Programme ch4_34.c
g) Algorithme dinsertion dune sous-liste dans une
liste.
Soit le schma :
liste

schma :
liste precedent

ptk

lment
supprimer

sliste

(2)

(1)

Algorithme : Suppression du kime lment.


Au pralable, on aurait pris soin de traiter le cas particulier du
premier lment.
Programme ch4_37.c
-schma rcursif : le raisonnement est :

Il faut chercher ladresse du dernier lment de la sousliste sliste+ afin dtablir la liaison (1). Linsertion peut
seffectuer par position ou par rapport loccurrence
dune valeur. Nous choisissons le cas de laccs associatif aprs la premire occurrence de la valeur val.
Algorithme : insertion dune sous-liste dans une liste.
Programme ch4_35.c
4.1.6.2. Algorithme de suppression dun lment dans
une liste.
On a le cas particulier de suppression du premier lment
qui a pour consquence de modifier ladresse de la liste.
Dans le cas gnral, il suffit de modifier le contenu dun
pointeur.
Schma :
liste

Elment
supprimer
Llment supprimer peut tre dtermine par sa
position ou par sa va leur (suppression associative).
a) Algorithme de suppression du premier lment.
On suppose que la liste nest pas vide.
Schma :
liste

Elment
supprimer
On suppose quon na plus besoin de llment et quon
rend la cellule au rservoir de cellules. Il faut donc
prserver ladresse de la tte de liste avant deffectuer la
modification de cette adresse.
Algorithme : suppression du 1er lment.
Programme ch4_36.c
b) Algorithme de suppression par position.
Supprimer le kime lment.
- schma itratif.
Il faut dterminer ladresse precedent de la cellule qui
prcde celle que lon veut supprimer : cest--dire
ladresse de la k-1ime cellule qui sera obtenue par la
fonction pointk. Ensuite si le kime cellule existe, on
modifie la valeur dadresse precedent.

liste+ = <>
la suppression est impossible. car val liste+. On
excute *possible = 0 ;...*
liste <>
>>k==1
on effectue la suppression en tte liste.
*possible = 1 ; supptete(*liste) ;..*
>>k1
supprimek((*liste)->suivant, k-1, *possible) ;
Algorithme : suppression du kime lment, schma rcursif.
Programme ch4_38.c
Si k a une valeur ngative ou nulle. Lalgorithme est correct
mais demande un parcours complet de la liste. Il est alors
souhaitable lappel de sassurer que k est positif afin dviter
ce parcours inutile.
b) Algorithme de suppression associative.
Supprimer la premire occurrence de val de la liste. Il faut
dfinir une variable boolenne possible qui nous permettra de
savoir si cette suppression a t ralise ou non.
- schma rcursif. On souhaite crire une fonction :
vide suppval (pointeur *liste, t avl, entier *possible)
//spcification ()((possible, suppression de la 1re //
occurrence de val) v (possible, suppression im-// possible))

liste+ = <>
la suppression est impossible. car val liste+. On
excute *possible = 0 ;.*
liste <>
>>liste->info==val
on effectue la suppression en tte liste.
*possible = 1 ; supptete(*liste) ;..*
>>liste->infoval
suppval((*liste)->suivant, val, *possible) ;
Algorithme : suppression associative, schma rcursif.
Programme ch4_39.c
- schma itratif : aprs avoir trait le cas de suppression du
premier lment, on utilise le raisonnement suivant dans le cas
gnral : pour supprimer la cellule contenant la premire
occurrence de val, il faut connatre ladresse de la cellule
prcdente. Pour dterminer cette adresse, on peut, utiliser une
variable auxiliaire precedent et la variable liste ou utiliser liste
et liste->suivant.
Algorithme : suppression associative de la premire occurrence
de val, schma itratif.

Rakotoasimbahoaka Cyprien Robert

anne 2008

49