Beruflich Dokumente
Kultur Dokumente
Philippe Gambette
2 Invariants 8
2.1 Séance 4 (19/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.1.1 Arrêt et invariants de l'algorithme 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.1.2 Arrêt et invariants de l'algorithme 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Séance 5 (24/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.1 Invariant et correction de l'algorithme 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.2 Invariant et correction de l'algorithme 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.3 Correction de l'algorithme 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Séance 6 (26/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.1 Correction de l'algorithme de recherche séquentielle en tableau trié . . . . . . . . . . . . 11
2.3.2 Correction de l'algorithme de multiplication par additions successives . . . . . . . . . . 12
2.3.3 Invariant de l'algorithme de recherche dichotomique modié . . . . . . . . . . . . . . . . 13
3 Complexité 14
3.1 Séance 6 (26/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.1.1 Complexité de l'algorithme 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4 Listes chaînées 15
4.1 Séance 9 (14/11/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.1.1 Familiarisation avec les listes chaînées . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.2 Séance 10 (28/11/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.2.1 Algorithmes sur les listes chaînées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.2.2 Adresse de la dernière cellule d'une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.2.3 Premier élément mis à la n d'une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2.4 Suppression de tous les éléments de valeur donnée d'une liste . . . . . . . . . . . . . . . 17
4.3 Séance 11 (07/12/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.3.1 Suppression de tous les doublons d'une liste . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.3.2 Miroir d'une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.3.3 Concaténation de deux listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.3.4 Familiarisation avec les listes doublement chaînées . . . . . . . . . . . . . . . . . . . . . 19
4.4 Exercices non corrigés en TD (28/12/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.4.1 Miroir d'une liste doublement chaînée . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.4.2 Concaténation de deux listes doublement chaînées . . . . . . . . . . . . . . . . . . . . . 20
1
5 Arbres 22
5.1 Séance 12 (12/12/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.1.1 Familiarisation avec les arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.1.2 Hauteur d'un arbre binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.1.3 Nombre de feuilles d'un arbre binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.2 Séance 13 (12/12/2007, 13/12/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.2.1 Intermède complexité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.2.2 Nombre de n÷uds de profondeur xée d'un arbre binaire . . . . . . . . . . . . . . . . . 23
5.2.3 Eeuillage d'un arbre binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Avertissement
Ce document contient éventuellement des erreurs volontaires, que j'ai indiquées pendant les séances de TD.
Je signale aussi que la pratique de recherche des exercices pendant la séance de TD est indispensable pour
s'entraîner, et déconseille cordialement l'utilisation exclusive de ce corrigé (la veille de l'examen par exemple)
sans avoir assisté aux séances.
Signalez-moi toute erreur involontaire à gambette@lirmm.fr. Je remercie pour cela (j'espère que la liste s'al-
longera) :
Cindy Sartre
Les cours d'algorithmique de L1 sont disponibles à l'adresse http://www.lirmm.fr/~vilarem/FLIN101/.
AT X pour que vous puissiez participer à la rédaction de ce corrigé est
Les indications sur l'utilisation du langage L E
disponible avec le chier source de ce document à l'adresse http://www.lirmm.fr/~gambette/EnsAlgo.php.
2
Chapitre 1
1.1.2 Algorithme 2
En considérant que renvoyer permet de terminer l'algorithme en arrêtant les boucles en cours :
Alternative "tordue" qui évite la cassure du renvoyer en milieu de boucle pour, avec un tant que :
1.1.3 Algorithme 4
T [1..n, 1..n] est une sorte de matrice de 0 et de 1, T [i, j] représente l'entier à la ligne i et à la colonne j.
Pour la culture. . .
Remarquons que comme il y a trois boucles (deux pour et une tant que imbriquées, la complexité de l'algo-
rithme 4 proposé est en O(n3 ). On peut en obtenir un en O(n2 log n) de la manière suivante : trier les lignes
3
Données : A[1..n] et B[1..n] deux tableaux de n entiers et Som un entier.
Résultat : Renvoie Vrai s'il existe i, j ∈ J1, nK tels que A[i] + B[j] = Som, renvoie Faux sinon.
début
i ← 1; j ← 1;
tant que j < n + 1 et A[i] + B[j] 6= Som faire
si i = n alors
j ← j + 1;
i ← 0;
sinon
i ← i + 1;
n
n
si j = n + 1 alors
renvoyer Faux;
sinon
renvoyer Vrai;
n
n
Algorithme 3 : Somme?( d A[1..n] : tableau d'entiers, d B[1..n] : tableau d'entiers, d Som : entier) :
booléen
4
du tableau en O(n2 log n) (chaque comparaison de deux lignes se fait en O(n)), puis parcourir chaque ligne du
tableau pour vérier si elle est égale à la suivante.
On peut même être encore plus astucieux en utilisant le fait que le tableau contient seulement des 0 et des 1
et en commençant par le trier par un tri par base (tri radix), avant de comparer chaque ligne avec la suivante,
pour obtenir une complexité totale en O(n2 ).
5
Données : N, M ∈ N∗
Résultat : renvoie pgcdN, M .
1 Variables : n, m entiers
2 début
3 n ← N; m ← M;
4 tant que n 6= 0 et m 6= 0 faire
5 si m > n alors
6 m←m−n
7 sinon
8 n←n−m
9 n
10 n
11 renvoyer m + n;
12 n
Algorithme 6 : PGCD(d N, M : entier) : entier
mk+1 = mk
Lignes 7 et 8 : n ← n − m donne : ∀k, mk ≤ nk ⇒
nk+1 = nk − mk
On peut alors utiliser ces égalités mathématiques pour démontrer les propriétés demandées.
Montrons maintenant que m décroit pendant l'exécution de l'algorithme, en calculant mk+1 − mk . Deux cas se
présentent :
si mk > nk , mk+1 − mk = mk − nk − mk = −nk ≤ 0
sinon, mk+1 − mk = mk − mk = 0 ≤ 0
donc la suite (mk ) est décroissante (pas nécessairement strictement).
De même on peut aussi montrer que (nk ) est décroissante (pas nécessairement strictement).
Les expressions n−m et m−n ne sont pas nécessairement positives, ni monotones, |n − m| n'est pas nécessai-
rement monotone non plus, on peut le prouver en exhibant un contre-exemple. En initialisant avec N = 10 et
M = 9, on obtient :
k 0 1 2
nk 10 1 1
mk 9 9 8
m k − nk 1 & -8 % -7
|mk − nk | 1 % 8 & 7
Aucune des expressions proposées pour le moment ne nous permet donc de conclure quant à l'arrêt de l'algo-
rithme 8. La stricte décroissance de la suite à valeurs entièresn + m va nous permettre de le prouver.
Fixonsk ∈ N, et notons uk = nk + mk . Deux cas se présentent :
si mk > nk alors uk+1 −uk = mk+1 +nk+1 −mk −nk = mk −nk +nk −mk −nk donc uk+1 −uk = −nk < 0
puisque nk > 0.
sinon, uk+1 − uk = mk+1 + nk+1 − mk − nk = nk − mk + mk − mk − nk = −mk < 0 puisque mk > 0.
Dans tous les cas, tant que l'algorithme ne s'arrête pas, la suite (uk ) est strictement décroissante, et à
valeurs entières. Elle nira donc par atteindre 0 à un certain rang kf et on aura alors nkf = 0 et mkf = 0, ce
qui correspond à la condition d'arrêt de l'algorithme.
6
On montre similairement que l'expression m∗n est aussi décroissante strictement et à valeurs dans N.
On pourrait choisir pour f la fonction suivante : (n, p) 7→ n qui est bien à valeurs entières et strictement
décroissante. Le problème est que cela nous permet seulement d'en conclure qu'elle atteindra forcément 0, ce
qui donnera n = 0, ce qui ne correspond pas à l'arrêt des appels récursifs (qui a lieu quand p=0 ou n=p). Il
faut donc trouver autre chose.
La fonction (n, p) 7→ n − p est décroissante mais pas strictement, elle ne convient donc pas non plus.
La fonction (n, p) 7→ Cnp = coefBin(n,p) conviendrait, encore faut-il le prouver, ce qui n'est pas complète-
ment évident, et il resterait alors à prouver que quand elle atteint 1 on a bien p = 0 ou n = p.
7
Chapitre 2
Invariants
= 2Ik + 2 + 1 − Zk − 2
= 2Ik + 1 − Zk
=0 (par l'hypothèse de récurrence)
Donc la propriété est intialisée et héréditaire, elle est donc vraie pour tout k ∈ N, et l'invariant 2I + 1 = Z est
bien démontré.
Montrons l'invariant M = N − I 2.
Soit Mk la valeur de la variable M à la k -ième boucle tant que. Montrons par récurrence sur k que
∀k ∈ N, Mk = N − Ik2 .
I au rang 0, M0 = N = N − 02 = N − I02 .
H soit k ∈ N, Mk = N − Ik2 ⇒ Mk+1 = N − Ik+1
2
?
2
) = Mk − Zk − N − (Ik + 1)2
Mk+1 − (N − Ik+1 (algo)
= Mk − Z k − N + Ik2 + 2Ik + 1
= Mk − (N − Ik2 ) − Zk + 2Ik + 1
=0 (h.r. + question précédente)
8
Donc la propriété est intialisée et héréditaire, elle est donc vraie pour tout k ∈ N, et l'invariant M = N − I2
est bien démontré.
d'après les deux premiers invariants. Or à la n de l'algorithme la condition d'arrêt de la boucle tant que
n'est pas vériée donc Z − M > 0, ce qui fournit bien l'inégalité voulue, et donc la correction de l'algorithme
en passant à la racine : √ √
I≤ N < I + 1 ⇔ I = b Nc
= Ai + 3 − 3X + 3Ci − 3
= Ai − 3(X − Ci )
=0 (h.r.)
Donc la propriété est intialisée et héréditaire, elle est donc vraie pour tout i ∈ N, et l'invariant Ai = 3(X −Ci )+1
est bien démontré.
=0 (h.r.)
Donc la propriété est intialisée et héréditaire, elle est donc vraie pour tout i ∈ N, et l'invariant Bi = 3(X − Ci )2
est bien démontré.
9
Donc la propriété est intialisée et héréditaire, elle est donc vraie pour tout i ∈ N, et l'invariant Zi = (X − Ci )3
est bien démontré.
A la n de l'algorithme 13, qui renvoie Z, on a C = 0, donc d'après l'invariant il calcule (X − 0)3 c'est à dire
3
X .
Remarques :
Cet algorithme s'appelle l'algorithme de PGCD par diérences successives. On utilise classiquement l'algo-
rithme d'Euclide, par divisions successives, pour calculer le PGCD. Eectivement l'algorithme par diérences
successives peut avoir une complexité assez mauvaise, regardez par exemple ce qui se passe quand on essaie de
calculer PGCD(n, 1).
10
2.2.3 Correction de l'algorithme 11
On commence par voir sur un exemple ce que calcule l'algorithme, en appelant ik (respectivement r1k , r2k ,
r3k ) la valeur de la variable i (respectivement r1 , r2 , r3 ) à la n de la k -ième itération de la boucle tant que.
Pour n=6:
k 0 1 2 3 4 5 6
r3i × 0 1 1 2 3 5
r1i 0 1 1 2 3 5 8
r2i 1 1 2 3 5 8 13
i 0 1 2 3 4 5 6
Ceci nous permet de supposer que r1i = bo(i), r2i = bo(i + 1) et r3i = bo(i − 1). Pour le démontrer, on
peut procéder de deux façons :
Première démonstration : une habile récurrence pour r1 , puis le reste.
Montrons par récurrence sur i que ∀i ∈ N, r1i = bo(i).
I au rang 1, r11 = 1 = bo(1).
H soit i ∈ N, ∀k ≤ i, r1k = bo(k) ⇒ r1i+1 = bo(i + 1) ?
r1i+1 = r2i = r3i + r2i−1 = r1i + r1i−1 = bo(i + 1).
Ainsi l'égalité est initialisée et héréditaire, elle est donc vraie pour tout i et donc r1i = bo(i).
On peut en déduire les deux autres inégalités : ∀i ∈ N, r2i = r1i+1 = bo(i + 1), et ∀i ∈ N∗ , r3i = r1i−1 =
bo(i − 1), et l'égalité est aussi vraie pour i = 0.
Seconde démonstration : tout en même temps, c'est plus facile.
Montrons par récurrence sur i que ∀i ∈ N, r1i = bo(i), r2i = bo(i + 1), et r3i = bo(i − 1).
I au rang 1, r11 = 1 = bo(1), r21 = 1 = bo(2), et r31 = 0 = bo(0).
H soit i ∈ N, r1i = bo(i), r2i = bo(i + 1), et r3i = bo(i − 1) ⇒ r1i+1 = bo(i + 1), r2i+1 = bo(i + 2),
et r3i+1 = bo(i) ?
r1i+1 = r2i = bo(i + 1) (par h.r.). r3i+1 = r1i = bo(i) (par h.r.). r2i+1 = r3i+1 + r2i = bo(i)+ bo(i + 1)
(par égalité précédente et h.r.) donc r2i+1 = bo(i + 2).
Ainsi les trois égalités sont initialisées et héréditaires, donc vraies pour tout i de N.
Données : T [1..N ] : tableau d'entiers trié dans l'ordre croissant, e : entier recherché dans le tableau
Résultat : renvoie Vrai si e est un élément du tableau T , Faux sinon.
Variable : i entier.
début
i ← 1;
tant que i ≤ N et T [i] < e faire
i ← i + 1;
n
renvoyer (i ≤ N et T [i] = e);
n
Algorithme 7 : Recherche(d T [1..N ] : tableau, d e : entier) : booléen
Invariant 1
Montrons par récurrence sur k que ∀k ≥ 1, ∀j ∈ [1, ik − 1], T [j] < e
Initialisation : au rang k = 1, on a exécuté la boucle tant que une fois, donc on a bien T [1] = e.
11
Hérédité : supposons qu'à un certain rang k ≥ 1, ∀j ∈ [1, ik − 1], T [j] < e, et que la boucle tant que
s'exécute k fois. Alors au début de la k -ième T [ik ] < e, donc en ajoutant cette
itération on a bien testé que
inégalité à celles de l'hyptohèse de récurrence on obtient ∀k ≥ 1, ∀j ∈ [1, ik ], T [j] < e.
La propriété étant initalisée et héréditaire, elle est vraie pour tout k ≥ 1, c'est à dire si la boucle tant que
s'exécute une fois ou plus.
Prouvons maintenant la correction de l'algorithme. S'il renvoie Vrai, alors i ≤ N et T [i] = e, on a donc bien
trouvé une case du tableau, la i-ième, qui contient e. S'il renvoieFaux, alors (i ≤ N et T [i] = e) est faux, donc
l'un des deux termes de la conjonction est faux :
soit i > N , alors l'invariant démontré arme qu'aucune des N cases du tableau ne contient e.
soit i ≤ N et T [i] 6= e. L'algorithme s'est arrêté, donc est sorti de la boucle, donc la condition de boucle
T [i] < e n'était pas vériée, donc T [i] > e. Or le tableau contient des entiers rangés par ordre croissant
donc e n'est pas contenu dans la i-ième case ni aucune à droite. D'autre part l'invariant nous arme
directement que e n'est contenu dans aucune des i − 1 premières cases. Finalement e n'est dans aucune
des N cases du tableau.
On a donc bien démontré que l'algorithme est correct.
Invariant 2
Au début k -ième itération de la boucle tant que on teste que T [ik−1 ] < e. Or ik−1 = ik − 1 d'après
l'algorithme, donc on a bien pour tout k ≥ 1, T [ik − 1] < e.
Prouvons maintenant la correction de l'algorithme. S'il renvoie Vrai, alors i ≤ N et T [i] = e, on a donc bien
trouvé une case du tableau, la i-ième, qui contient e. S'il renvoieFaux, alors (i ≤ N et T [i] = e) est faux, donc
l'un des deux termes de la conjonction est faux :
soit i > N, alors l'invariant démontré arme que la i − 1-ième case du tableau contient une valeur
inférieure strictement à e, or les cases précédentes contiennent des valeurs strictement inférieures puisque
le tableau est rangé dans l'ordre croissant, donc e n'est pas contenu dans le tableau.
soit i ≤ N et T [i] 6= e. L'algorithme s'est arrêté, donc est sorti de la boucle, donc la condition de boucle
T [i] < e n'était pas vériée, donc T [i] > e. Or le tableau contient des entiers rangés par ordre croissant
donc e n'est pas contenu dans la i-ième case ni aucune à droite. D'autre part l'invariant nous arme
que T [i − 1] < e, et le tableau est rangé par ordre croissant, donc e n'est contenu dans aucune des i − 1
premières cases. Finalement e n'est dans aucune des N cases du tableau.
On a donc bien démontré que l'algorithme est correct.
Remarquons que l'invariant 2 était plus direct à démontrer (sans récurrence), mais demande quelques lignes
supplémentaires pour la preuve de correction. Lorsqu'on demande un invariant il est possible qu'il y ait plusieurs
possibilités, il s'agit d'en choisir un qui soit susamment simple à démontrer et à utiliser pour la preuve de
correction.
Précisons aussi que l'invariant a été démontré dans tous les cas où la boucle tant que est exécutée au moins
une fois. Ceci dit le cas où elle ne s'exécute pas ne pose pas de problème, les preuves de correction restent
valides, on peut juste se débarasser de ce qui suit le D'autre part (cela concerne les i−1 premières cases
qui ne sont alors pas dénies puisque i = 1).
Données : m, n : entiers
Résultat : renvoie le produit mn.
Variables : p, i, entiers.
début
p ← 0 ; i ← 0;
tant que i < n faire
p ← p + m; i ← i + 1;
n
renvoyer p;
n
Algorithme 8 : Produit(d m, n : entiers) : entier
12
L'invariant est p = mi. Appelons pk , ik , les valeurs de p et i au début de la k -ième boucle tant que et
démontrons par récurrence sur k que pk = mik .
I p1 = 0 = m × 0 = mi0 .
H pk = mik ⇒ pk+1 = mik+1 ? pk+1 = pk + m = mik + m = m(ik + 1) = mik+1
Ainsi la propriété est initialisée et héréditaire, donc vraie pour tout k , et l'égalité proposée est bien un
invariant de l'algorithme.
13
Chapitre 3
Complexité
Données : A, B : entiers
Résultat : renvoie la puissance AB .
Variables : p, i, x, entiers.
début
p ← 1; x ← A; i ← B ;
tant que i 6= 0 faire
si i modulo 2 = 1 alors
p ← p × x;
i ← i − 1;
n
x ← x × x;
i ← i/2;
n
renvoyer p;
n
Algorithme 9 : ExponentiationRapide(d A, B : entiers) : entier
1 http://fr.wikipedia.org/wiki/Exponentiation_rapide
14
Chapitre 4
Listes chaînées
(a) (b)
(c) (d)
(e) (f )
(g) (h)
(i) (j)
(k) (l)
15
(m) (n)
Fig. 4.1 Utilisations de listes chaînées : après la ligne 1 (a), 2 (b), 3 (c), 4 (d), 5 (e), réorganisa-
tion (f), après la ligne 6 (g), réorganisation (h), après la ligne 7 (i), 8 (j), 9 (k), réorganisation
(l), après la ligne 10 (m), 11 (n).
Attention à la condition d'arrêt, on pourra préférer s'arrêter après avoir atteint le dernier élément, c'est à
dire quand Q= NULL, ou en l'atteignant, c'est à dire quand Q↑ succ = NULL.
Quand ce n'est pas précisé dans les exercices sur les listes, n est la taille de la liste (son nombre d'éléments).
16
4.2.3 Premier élément mis à la n d'une liste
Notons qu'on s'arrête avant d'être arrivé à la n de la liste, c'est à dire qu'on quitte la boucle dès qu'on
atteint le dernier élément.
L'algorithme Supprimer vu en cours a une complexité en O(n), donc SupprimeValeur a une complexité en
0(n2 )
En utilisant une liste doublement chaînée, l'idée est que la suppression peut se faire en temps constant
(comme on a alors accès à l'adresse du dernier élément, il sut de faire pointer le successeur de cet élément vers
le successeur de son successeur). Ainsi la complexité totale de SupprimeValeur en utilisant une liste doublement
chaînée serait en O(n).
17
Données : L : liste simplement chaînée
Résultat : Modie L en supprimant tous ses doublons, c'est à dire ses éléments qui auraient même
valeur que leur successeur
Variable : Q, liste simplement chaînée.
début
Q ← L;
si L 6= NULL alors
tant que Q ↑ succ 6= NULL faire
valpred ← Q ↑ info;
Q ← Q ↑ succ;
si Q ↑ info = valpred alors
Supprimer(Q,L);
n
n
n
n
Algorithme 14 : SupprimeDoublons(L : liste simplement chaînée)
18
4.3.2 Miroir d'une liste
On cherche à modier l'algorithme 16 pour inverser une liste simplement chaînée en place, c'est à dire
sans créer de nouvelle liste. Pour cela on va faire avancer le long de la liste trois pointeurs sur trois éléments
consécutifs de la liste à modier, pour garder en mémoire leurs adresses et pouvoir faire les modications.
19
Données : L1, L2 : listes simplement chaînées
Résultat : renvoie L1 à qui on a concaténé L2
Variable : Q, liste simplement chaînée.
début
si L = NULL alors
renvoyer L2;
n
sinon
Q ← L;
tant que Q ↑ succ 6= NULL faire
Q←Q↑ succ;
n
Q↑ succ ← L2;
renvoyer L1;
n
n
Algorithme 18 : Concatène(L : liste simplement chaînée) : liste simplement chaînée
L ← créerTriplet(NULL,NULL,NULL);
Q ← créerTriplet(L, 4, L);
L ↑ succ ← Q;
L ↑ pred ← Q;
R ← créerTriplet(L ↑ pred, 6, L);
Q ↑ succ ← R;
L ↑ succ ← Q;
L ↑ pred ← R;
Algorithme 19 : Création d'une liste doublement chaînée à 2 éléments contenant 4 et 6.
Sur la liste doublement chaînée ainsi créée, comment supprimer le dernier élément pour obtenir une liste
doublement chaînée à 1 élément (contenant donc la valeur 4) ? Par exemple on applique l'algorithme 20.
L ↑ pred ← Q;
Q ↑ succ ← L;
Algorithme 20 : Suppression du dernier élément de la liste créée précédemment.
20
Données : L : liste doublement chaînée
Résultat : Renvoie une liste constituée des éléments de L dans l'ordre inverse
Variables : P , Q, éléments d'une liste doublement chaînée.
début
P ← L;
Q ← L ↑ succ;
si Q 6= NULL alors
tant que Q 6= L faire
//On traite l'élément P en inversant son successeur stocké dans Q avec son prédécesseur:
P ↑ ← P ↑ pred;
succ
P ↑ ← Q;
pred
//On traitera Q, l'ancien successeur de P , à la prochaine étape:
P ← Q;
Q ← Q ↑ succ;
n
//Il reste à traiter le dernier élément P de la liste, qui a pour successeur Q = L
P ↑ succ ←P ↑ pred;
P ↑ pred ← Q;
n
renvoyer L;
n
Algorithme 21 : Miroir(L : liste doublement chaînée) : liste doublement chaînée
21
Chapitre 5
Arbres
n
n
Algorithme 23 : Hauteur(A : arbre binaire) : entier
22
Données : A : arbre binaire
Résultat : nombre de feuilles de l'arbre A
début
si A = NULL alors
renvoyer 0;
n
sinon si A ↑ sag = NULL et A ↑ sag = NULL alors
renvoyer 1;
n
sinon
renvoyer NombreFeuilles(A ↑ sag)+NombreFeuilles(A ↑ sad);
n
n
Algorithme 24 : NombreFeuilles(A : arbre binaire) : entier
a = n − 1 = 2f − 2
23
Données : A : arbre binaire, p : entier
Résultat : renvoie le nombre de n÷uds de profondeur p de l'arbre A
début
si p = 0 et A 6= NULL alors
renvoyer 1;
n
sinon si A = NULL alors
renvoyer 0
n
sinon
renvoyer NombreN÷udsProfondeur(A ↑ sag, p − 1)+NombreN÷udsProfondeur(A ↑ sad, p − 1);
n
n
Algorithme 25 : NombreN÷udsProfondeur(A : arbre binaire, p : entier) : entier
24
Chapitre 6
Données : A : arbre
Résultat : Renvoie une liste contenant la notation postxe correspondant à l'arbre A
début
si A = NULL alors
renvoyer NULL;
n
sinon
si A ↑ sag = NULL et A ↑ sad = NULL alors
renvoyer créerListe(A ↑ info,NULL);
n
sinon si A ↑ sag = NULL alors
renvoyer Concaténer Postxe(A ↑ sad),créerListe(A ↑ info,NULL) ;
n
sinon si A ↑ sad = NULL alors
renvoyer Concaténer Postxe(A ↑ sag),créerListe(A ↑ info,NULL) ;
n
sinon
renvoyer Concaténer
Postxe(A ↑ sad),Concaténer(Postxe(A ↑ sad),créerListe(A ↑
info,NULL)) ;
n
n
n
Algorithme 27 : Postxe(A : arbre) : liste simplement chaînée
25
Données : P : pile contenant une notation postxée dont le dernier élément est en haut de la pile
Résultat : Renvoie la valeur de l'expression dont la notation postxée est stockée dans P
Variables : R1, R2 : entiers, operation : symbole.
début
si PileVide?(P ) alors
renvoyer 0;
n
sinon
operation ← sommetPile(P );
dépiler(P );
si operation = + ou operation = ∗ alors
R1 ← Evaluer(P ); //P est alors modiée !
R2 ← Evaluer(P );
renvoyer R1 operation R2;
n
sinon
renvoyer operation; //operation est alors un entier.
n
n
n
Algorithme 28 : Evaluer(P : pile) : entier
26
Données : A : arbre
Résultat : Renvoie une liste chaînée correspondant au parcours en largeur de A
Variables : L, liste chaînée, F, le.
début
L ← NULL;
F ← créerFile;
si A 6= NULL alors
ajouterFile(F, A);
tant que non FileVide?(F ) faire
//On traite le premier élément de la le :
A ← têteFile(F );
retirerFile(F );
L← créerListe(A ↑ info,L);
//On ajoute à la n de la le les ls éventuels, à traiter plus tard :
si A ↑ sag 6= NULL alors
ajouterFile(F, A ↑ sag);
n
si A ↑ sad 6= NULL alors
ajouterFile(F, A ↑ sad);
n
n
n
//La liste L a été construite dans le mauvais sens, son premier élément est celui visité en dernier,
//donc de profondeur maximale dans A :
renvoyer Miroir(L);
n
Algorithme 29 : ParcoursLargeur(F : le) : liste simplement chaînée
27
Données : T 1, T 2 : tableaux de respectivement m et n entiers
Résultat : Renvoie le nombre d'entiers présents dans les deux tableaux.
Variables : L, liste chaînée ; t, entier.
début
L← NULL;
pour i de 1 à m faire
j ← 1;
tant que j < n et T 1[i] 6= T 2[j] faire
j ← j + 1;
n
si j < n alors
//T 1[i] = T 2[j] donc on ajoute T 1[i] à L :
L← créerListe(T 1[i], L);
n
n
//Élimination des doublons de L :
Q ← L;
tant que Q 6= N U LL faire
supprimeValeur(Q ↑ succ,Q ↑ info);
Q←Q↑ succ;
n
//Taille de la liste L :
Q ← L;
t ← 0;
tant que Q 6= N U LL faire
t ← t + 1;
Q ← Q ↑ succ;
n
renvoyer t;
n
Algorithme 30 : TailleIntersectionNaif(T 1, T 2 : tableaux) : entier
28
Données : T 1, T 2 : tableaux triés de respectivement m et n entiers
Résultat : Renvoie le nombre d'entiers présents dans les deux tableaux.
Variables : d, t, entier.
début
i ← 1;
j ← 1;
d ← 0;
t ← 0;
tant que i < m et j < n faire
si T 1[i] = T 2[j] alors
si T 1[i] 6= d alors
//T 1[i] n'a pas encore été trouvé dans T 1 et T 2 :
t ← t + 1;
//d contient le dernier élément trouvé à la fois dans T 1 et T 2 :
d ← T 1[i];
n
i ← i + 1;
j ← j + 1;
n
sinon si T 1[i] < T 2[j] alors
i ← i + 1;
n
sinon
j ← j + 1;
n
n
renvoyer t;
n
Algorithme 32 : TailleIntersection2Triés(T 1, T 2 : tableaux) : entier
29