Vous êtes sur la page 1sur 30

Correction des TD d'algorithmique de L2

Philippe Gambette

1er janvier 2008

Table des matires

Table des matires 1 Rvisions, preuves d'arrt


1.1 Sance 1 (10/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.1 1.1.2 1.1.3 1.2 1.2.1 1.2.2 1.2.3 1.3 1.3.1 1.3.2 Algorithme 1 Algorithme 2 Algorithme 4 Algorithme 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 3
3 3 3 3 5 5 5 5 5 5 7

Sance 2 (12/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Preuve d'arrt de l'algorithme 6 Preuve d'arrt de l'algorithme 7 Preuve d'arrt de l'algorithme 8

Sance 3 (17/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Algorithme de calcul des coecients binomiaux . . . . . . . . . . . . . . . . . . . . . . .

2 Invariants
2.1 Sance 4 (19/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 2.1.2 2.2 2.2.1 2.2.2 2.2.3 2.3 2.3.1 2.3.2 2.3.3 Arrt et invariants de l'algorithme 15 Arrt et invariants de l'algorithme 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8
8 8 9 10 10 10 11 11 11 12 13

Sance 5 (24/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Invariant et correction de l'algorithme 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . Invariant et correction de l'algorithme 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . Correction de l'algorithme 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Correction de l'algorithme de recherche squentielle en tableau tri . . . . . . . . . . . . Correction de l'algorithme de multiplication par additions successives . . . . . . . . . . Invariant de l'algorithme de recherche dichotomique modi . . . . . . . . . . . . . . . .

Sance 6 (26/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Complexit
3.1 Sance 6 (26/10/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 Complexit de l'algorithme 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14
14 14

4 Listes chanes
4.1 4.2 Sance 9 (14/11/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 4.2.1 4.2.2 4.2.3 4.2.4 4.3 4.3.1 4.3.2 4.3.3 4.3.4 4.4 4.4.1 4.4.2 Familiarisation avec les listes chanes Algorithmes sur les listes chanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sance 10 (28/11/2007) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15
15 15 16 16 16 17 17 17 17 19 19 19 20 20 20

Adresse de la dernire cellule d'une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . Premier lment mis la n d'une liste Suppression de tous les lments de valeur donne d'une liste

Sance 11 (07/12/2007)

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Suppression de tous les doublons d'une liste . . . . . . . . . . . . . . . . . . . . . . . . . Miroir d'une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Concatnation de deux listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Familiarisation avec les listes doublement chanes Miroir d'une liste doublement chane

Exercices non corrigs en TD (28/12/2007)

Concatnation de deux listes doublement chanes

5 Arbres
5.1 Sance 12 (12/12/2007) 5.1.1 5.1.2 5.1.3 5.2 5.2.1 5.2.2 5.2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Familiarisation avec les arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hauteur d'un arbre binaire Nombre de feuilles d'un arbre binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Intermde complexit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22
22 22 22 22 23 23 23 23

Sance 13 (12/12/2007, 13/12/2007)

Nombre de nuds de profondeur xe d'un arbre binaire Eeuillage d'un arbre binaire

6 Autres structures de donnes


6.1 Sance 14 (14/12/2007) 6.1.1 6.1.2 6.1.3 6.1.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Notation postxe d'un arbre Pile pour l'valuation d'une expression postxe . . . . . . . . . . . . . . . . . . . . . . . File pour un parcours en largeur d'arbre . . . . . . . . . . . . . . . . . . . . . . . . . . . Taille de l'intersection de deux tableaux d'entiers . . . . . . . . . . . . . . . . . . . . . .

25
25 25 25 26 26

Avertissement
Ce document contient ventuellement des erreurs volontaires, que j'ai indiques pendant les sances de TD. Je signale aussi que la pratique de recherche des exercices pendant la sance de TD est indispensable pour s'entraner, et dconseille cordialement l'utilisation exclusive de ce corrig (la veille de l'examen par exemple) sans avoir assist aux sances. Signalez-moi toute erreur involontaire longera) :  Cindy Sartre Les cours d'algorithmique de L1 sont disponibles l'adresse

gambette@lirmm.fr.

Je remercie pour cela (j'espre que la liste s'al-

A Les indications sur l'utilisation du langage L T X pour que vous puissiez participer la rdaction de ce corrig est E disponible avec le chier source de ce document l'adresse http://www.lirmm.fr/~gambette/EnsAlgo.php.

http://www.lirmm.fr/~vilarem/FLIN101/.

Chapitre 1
Rvisions, preuves d'arrt

1.1

Sance 1 (10/10/2007)

1.1.1 Algorithme 1
Donnes : T [1..n] tableau d'entiers, x un entier. Rsultat : P P est un des lments de T les plus proches de x, c'est dire P P dbut
|x P P | |x T [i]|. T
et

i 1, n

n

pour tous les i de 2 n faire si |x T [i] < |x P P | alors P P n

P P T [1];

T [i];

Algorithme 1 : PlusProche(d T [1..n] : tableau d'entiers, d x : entier, r P P

: entier)

1.1.2 Algorithme 2
En considrant que

renvoyer permet de terminer l'algorithme en arrtant les boucles en cours :

Donnes : A[1..n] et B[1..n] deux tableaux de n entiers et Som un entier. Rsultat : Renvoie Vrai s'il existe i, j [1..n] tels que A[i] + B[j] = Som, renvoie Faux sinon. dbut pour tous les i de 1 n faire pour tous les j de 1 n faire si A[i] + B[j] = Som alors renvoyer Vrai; n n renvoyer Faux; n Algorithme 2 : Somme?(d A[1..n] : tableau d'entiers, d B[1..n] : tableau d'entiers, d Som : entier)
boolen 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]

Pour la culture. . .

est une sorte de matrice de 0 et de 1,

T [i, j]

reprsente l'entier la ligne

et la colonne

j.

Remarquons que comme il y a trois boucles (deux rithme 4 propos est en

O(n3 ).

pour et une tant que imbriques, la complexit de l'algoO(n2 log n)


de la manire suivante : trier les lignes

On peut en obtenir un en

Donnes : A[1..n] et B[1..n] deux tableaux de n entiers et Som un entier. Rsultat : Renvoie Vrai s'il existe i, j 1, n tels que A[i] + B[j] = Som, renvoie Faux sinon. dbut
i 1; j 1; tant que j < n + 1 et A[i] + B[j] = Som si i = n alors j j + 1; i 0;

faire

sinon n

i i + 1;

n Algorithme 3
boolen

n si j = n + 1 alors renvoyer Faux; sinon renvoyer Vrai; n


: Somme?(

A[1..n]

: tableau d'entiers,

B[1..n]

: tableau d'entiers,

Som

: entier) :

Donnes : T [1..n, 1..n] un tableau de 0 et de 1. Rsultat : Renvoie Vrai si et seulement si T possde deux lignes identiques, c'est dire ssi dbut pour tous les i de 1 n faire pour tous les j de 1 n faire
k 1; i = j 1, n / k 1, n
,

T [i, k] = T [j, k].

tant que T [i, k] = T [j, k] faire si k = n alors renvoyer Vrai; sinon n n


k k + 1;

n

n renvoyer Faux; Algorithme 4 : LignesEgales?(d T [1..n, 1..n] : tableau d'entiers) : boolen

n

du tableau en

O(n2 log n)

(chaque comparaison de deux lignes se fait en

O(n)),

puis parcourir chaque ligne du

tableau pour vrier si elle est gale la suivante. On peut mme tre encore plus astucieux en utilisant le fait que le tableau contient seulement des 0 et des 1 et en commenant 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 ).

1.2

Sance 2 (12/10/2007)

1.2.1 Algorithme 5
On n'utilise qu'un seul tableau

en considrant qu'on peut augmenter sa taille de

n + 1.

Donnes : T [1..n, 1..n] un tableau de 0 et de 1. Rsultat : T modi de telle sorte que e soit insr la bonne place parmi les m premiers lments (le dbut n
tableau

T [1..m + 1]

est donc tri).

i 1;

tant que e < T [i] et i m faire


i i + 1;

/* la i-ime case et celles sa droite doivent tre dcales d'une case droite pour pouvoir insrer e en i-ime position. */ j n; tant que j i faire T [j + 1] = T [j];

n

n

T [i] = e;

Algorithme 5 : InsrerTabTri(dr T [1..n] : tableau d'entiers, d m : entier, d e : entier)

1.2.2 Preuve d'arrt de l'algorithme 6


Soit

nk

la valeur de la variable

l'algorithme s'arrte, considrons donc le cas o

est impair, alors

k -ime itration de la boucle tant que. Si N = 0 ou N = 1 alors N > 1. Si N est pair alors on peut vrier que nk = 2k N , si k1 nk = 2 (N 1). Dans les deux cas la suite (nk ) crot vers + partir de son deuxime n
la donc la condition d'arrt du

terme si

N {0, 1}, /

tant que n'est pas atteinte, et l'algorithme ne s'arrte pas.

1.2.3 Preuve d'arrt de l'algorithme 7


Soit nk la valeur de la variable n la k -ime itration de la boucle tant que. Considrons la suite dnie par uk = |n 7|. (uk ) est valeurs entires. De plus, si nk > 7 alors nk+1 = nk 1 7 donc 0 nk+1 7 nk 7 donc 0 uk + 1 < uk . Si nk < 7 alors nk+1 = nk + 1 7 donc 0 7 nk 1 = 7 nk+1 < 7 nk donc 0 uk + 1 < uk . Donc la suite (uk ) est dcroissante strictement, et valeurs entires. Donc elle sera nulle un certain rang, la condition d'arrt de la boucle prouverons plus loin en utilisant un invariant.

tant que sera alors vrie, et l'algorithme s'arrtera.


N !.

Calculer le rsultat de l'algorithme 7 sur plusieurs exemples permet de remarquer qu'il calcule

Nous le

1.3

Sance 3 (17/10/2007)
k -ime itration de la boucle tant que, n et m en galits mathmatiques sur

1.3.1 Preuve d'arrt de l'algorithme 8


En notant

nk

et

mk

les valeurs respectives de

et

la

on les

transforme les lignes de l'algorithme faisant intervenir les variables termes des suites

(nk ) et (mk ). Lignes 3 : n N ; m M ;

donne :

Lignes 5 et 6 : m m n

donne :

n0 = N , m0 = M . mk+1 = mk nk k, mk > nk nk+1 = nk


5

1 2 3 4 5 6 7 8 9 10 11 12

Donnes : N, M N Rsultat : renvoie pgcdN, M .


Variables :

dbut

n, m

entiers

tant que n = 0 et m = 0 faire si m > n alors sinon n


mmn nnm

n N; m M;

n

n renvoyer m + n; Algorithme 6 : PGCD(d N, M


donne : : entier) : entier

Lignes 7 et 8 : n n m

k, mk nk

mk+1 = mk nk+1 = nk mk

On peut alors utiliser ces galits mathmatiques pour dmontrer les proprits demandes. Appelons mk (respectivement nk la valeur de la variable m (resp. n) la k -ime itration de la boucle tant que et montrons par rcurrence que k mk 0. Initialisation : m0 = M 0 Hrdit : Supposons qu' un certain rang k mk > 0 et montrons que mk+1 > 0. Deux cas se prsentent :  si  sinon,

mk > nk alors mk+1 = mk nk > 0, mk+1 = mk > 0 par l'hypothse de

rcurrence.

La proprit tant initialise et hrditaire, elle est vraie pour tout De mme on dmontre que Montrons maintenant que prsentent :  si donc la  sinon,

de

N.

k N, nk 0.
dcroit pendant l'excution de l'algorithme, en calculant

mk+1 mk .

Deux cas se

mk > nk , mk+1 mk = mk nk mk = nk 0 mk+1 mk = mk mk = 0 0 suite (mk ) est dcroissante (pas ncessairement strictement). (nk )
est dcroissante (pas ncessairement strictement).

De mme on peut aussi montrer que Les expressions

nm

et

mn

ne sont pas ncessairement positives, ni monotones,

|n m|

n'est pas ncessai-

rement monotone non plus, on peut le prouver en exhibant un contre-exemple. En initialisant avec

N = 10

et

M = 9,

on obtient :

k nk mk m k nk |mk nk |

0 10 9 1 1

1 1 9 -8 8

2 1 8 -7 7

Aucune des expressions proposes pour le moment ne nous permet donc de conclure quant l'arrt de l'algorithme 8. La stricte dcroissance de la suite valeurs entires Fixons

n + m va nous permettre de le prouver. k N, et notons uk = nk + mk . Deux cas se prsentent :  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'arrte pas, la suite (uk ) est strictement dcroissante, et valeurs entires. 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'arrt de l'algorithme.

On montre similairement que l'expression

mn

est aussi dcroissante strictement et valeurs dans

N.

1.3.2 Algorithme de calcul des coecients binomiaux


Rappel sur les coecients binomiaux : voir

Illustration de l'algorithme 9 : on peut voir se qui se passe sur le triangle de Pascal :


p=0
1 1 1 1 1 1 1 2 3 4 5 1 3 6 10 1 4 10 1 5 1 1 2 3 4 5 1 2 3 4 5

http://fr.wikipedia.org/wiki/Coefficient_binomial

n=0

coefBin pour calculer la valeur dans une certaine case (n, p), celui-ci renvoie 1 s'il est sur un des bords du triangle de Pascal, sinon il appelle rcursivement coefBin pour calculer les valeurs dans la case situe au-dessus, (n 1, p), et celle au-dessus gauche, (n 1, p 1).
A chaque appel de l'algorithme On va de nouveau chercher une expression entire qui dcroit chaque appel rcursif pour prouver l'arrt de l'algorithme. Les donnes chaque appel rcursif tant

et

qui sont dans

N,

on cherche une fonction

f : N2 N

strictement dcroissante.

On pourrait choisir pour qui donnera

la fonction suivante :

(n, p) n

qui est bien valeurs entires et strictement

dcroissante. Le problme est que cela nous permet seulement d'en conclure qu'elle atteindra forcment 0, ce

n = 0,

ce qui ne correspond pas l'arrt des appels rcursifs (qui a lieu quand

p=0 ou n=p).

Il

faut donc trouver autre chose. La fonction La fonction ment vident,

(n, p) n p est dcroissante mais pas strictement, elle ne convient donc pas non plus. p (n, p) Cn = coefBin(n,p) conviendrait, encore faut-il le prouver, ce qui n'est pas complteet il resterait alors prouver que quand elle atteint 1 on a bien p = 0 ou n = p.

Bref, passons la solution :

f : (n, p) n + p. Eectivement, pour le premier appel rcursif, on a f (n 1, p 1) f (n, p) = n 1 + p 1 (n + p) = 2 < 0. Pour le second appel rcursif on a f (n 1, p) f (n, p) = n 1 + p (n + p) = 1 < 0. Donc dans tous les cas n + p dcrot chaque appel rcursif. Etant valeurs entires, elle atteindra donc forcment 0, ce qui impliquera p = 0.

Chapitre 2
Invariants

2.1

Sance 4 (19/10/2007)

Les invariants, quoi a sert ?


Ce sont des proprits mathmatiques sur les variables d'un algorithme qui sont valables tout au long de son excution ( chaque itration d'une boucle, ou chaque appel rcursif ). On les utilise pour dmontrer sa correction, c'est dire prouver que l'algorithme renvoie bien le rsultat voulu. Pour prouver des invariants, on montre qu'ils sont maintenus de l'tape

l'tape

k+1

de l'excution, plus formellement c'est une dmonstration par (respectivement, une ingalit

rcurrence qu'il faut eectuer pour montrer que l'invariant est valable chaque tape. Rappelons que pour dmontrer une galit

A=B

terme et faire des transformations pour arriver l'autre, ou montrer que

A B ) on peut partir un AB = 0 (respectivement, AB 0).

2.1.1 Arrt et invariants de l'algorithme 15


L'algorithme 15 s'arrte car l'expression boucle on a

M Z est strictement dcroissante ( la k + 1-ime itration de la Mk+1 Zk+1 = Mk Zk Zk 2 < Mk Zk ) et valeurs entires. Elle deviendra donc forcment

ngative ce qui correspond la condition de sortie de la boucle Montrons l'invariant

tant que, donc l'algorithme s'arrte bien.


(respectivement

Z = 2I + 1. Zk (respectivement Ik ) la valeur de la variable Z tant que. Montrons par rcurrence sur k que k N, Zk = 2Ik + 1. Initialisation : au rang 0, 2I0 + 1 = 0 + 1 = 1 = Z0 . Hrdit : soit k N, 2Ik + 1 = Zk 2Ik+1 + 1 = Zk+1 ?
Pour cela appelons

I)

la

k -ime

boucle

2Ik+1 + 1 Zk+1 = 2(Ik + 1) + 1 (Zk + 2) = 2Ik + 2 + 1 Zk 2 = 2Ik + 1 Zk =0

(d'aprs l'algorithme)

(par l'hypothse de rcurrence)

Donc la proprit est intialise et hrditaire, elle est donc vraie pour tout bien dmontr. Montrons l'invariant

k N,

et l'invariant

2I + 1 = Z

est

M = N I 2.

Soit Mk la valeur de la variable M la k -ime boucle 2 k N, Mk = N Ik . 2 I au rang 0, M0 = N = N 02 = N I0 . 2 2 H soit k N, Mk = N Ik Mk+1 = N Ik+1 ?

tant que.

Montrons par rcurrence sur

que

2 Mk+1 (N Ik+1 ) = Mk Zk N (Ik + 1)2

(algo)

= Mk Z k N + = Mk (N =0
2 Ik )

2 Ik

+ 2Ik + 1

Zk + 2Ik + 1

(h.r. + question prcdente)

Donc la proprit est intialise et hrditaire, elle est donc vraie pour tout est bien dmontr. Montrons l'invariant

k N,

et l'invariant

M = N I2

M 0. Il n'y a mme pas besoin de rcurrence : pour k = 0, M0 = N 0 et k 1, Mk = Mk1 Zk1 0 d'aprs la condition de la boucle tant que, donc on a bien k 0, Mk 0.
Montrons que

I 2 N < (I +1)2 . Pour cela montrons qu'en n d'algorithme on a N I 2 0 et (I +1)2 N > 0. N I = M 0 d'aprs le deuxime et le troisime invariant. (I +1)2 N = I 2 +2I +1N = 2I +1M = Z M
2

d'aprs les deux premiers invariants. Or la n de l'algorithme la condition d'arrt de la boucle n'est pas vrie donc

tant que

Z M > 0,

ce qui fournit bien l'ingalit voulue, et donc la correction de l'algorithme

en passant la racine :

N <I +1I =

2.1.2 Arrt et invariants de l'algorithme 13


L'algorithme 13 s'arrte car la variable s'arrte. Appelons

a des valeurs entires et strictement dcroissantes, elle deviendra

donc ngative ou nulle, ce qui correspond la condition de sortie de boucle

tant que,

et donc l'algorithme

Ai

(respectivement

itration de la boucle

I H

tant que. Montrons par rcurrence sur i que i N, Ai = 3(X Ci ) + 1.


Ai+1 3(X Ci+1 ) + 1 = Ai + 3 3 X (Ci 1) = Ai + 3 3X + 3Ci 3 = Ai 3(X Ci ) =0
(h.r.) (algo)

Bi , Ci , Zi ) la valeur de la variable A (respectivment B , C , Z ) la n de la i-ime

au rang 0, soit

A0 = 1 = 3(X X) + 1 = 3(X C0 ) + 1. i N, Ai = 3(X Ci ) + 1 Ai+1 = 3(X Ci+1 ) + 1 ?

Donc la proprit est intialise et hrditaire, elle est donc vraie pour tout est bien dmontr. Montrons par rcurrence sur

i N, et l'invariant Ai = 3(X Ci )+1

I H

i que i N, Bi = 3(X Ci )2 . 2 2 au rang 0, B0 = 0 = 3(X X) = 3(X C0 ) . 2 2 soit i N, Bi = 3(X Ci ) Bi+1 = 3(X Ci+1 ) ?
2 2
(algo)

Bi+1 3(X Ci+1 )2 = Bi + 2Ai + 1 3 X (Ci 1) = Bi + 2Ai + 1 3 (X Ci ) + 1

= Bi + 2Ai + 1 3(X Ci )2 6(X Ci ) 3 = Bi 3(X Ci )2 + 6(X Ci ) + 2 + 1 6(X Ci ) 3 =0


(h.r.) (question prcdente)

Donc la proprit est intialise et hrditaire, elle est donc vraie pour tout est bien dmontr. Montrons par rcurrence sur

i N, et l'invariant Bi = 3(X Ci )2

I H

i que i N, Zi = (X Ci )3 . 3 3 au rang 0, Z0 = 0 = (X X) = (X C0 ) . 3 3 soit i N, Zi = (X Ci ) Zi+1 = (X Ci+1 ) ?


3
(algo)

Zi+1 (X Ci+1 )3 = Zi + Ai + Bi X (Ci 1) = Zi + Ai + Bi (X Ci ) + 1)

3 3 3
(h.r.+ questions prcdentes)

= (X Ci )3 + 3(X Ci ) + 1 + 3(X Ci )2 (X Ci ) + 1) = (X Ci )3 + 3(X Ci )2 + 3(X Ci ) + 1 (X Ci ) + 1) =0

Donc la proprit est intialise et hrditaire, elle est donc vraie pour tout est bien dmontr. A la n de l'algorithme 13, qui renvoie

i N,

et l'invariant

Zi = (X Ci )3

Z,

on a

C = 0,

donc d'aprs l'invariant il calcule

(X 0)3

c'est dire

2.2

Sance 5 (24/10/2007)

2.2.1 Invariant et correction de l'algorithme 7


Pour trouver son invariant on peut essayer d'excuter l'algorithme 7 sur plusieurs exemples et voir si l'on arrive trouver une certaine rgularit chaque itration de la boucle Commenons par un exemple avec

tant que.

la n de la

i ni fi

0 10 7!

i-ime boucle tant 1 2 9 8 7! 10 7! 10 9

que.

N = 10 > 7,

en appelant

ni

(respectivement

fi )

la valeur de la variable

3 7 7! 10 9 8 fi 10!
chaque tape, il surait de multiplier par : : 10, 10 9, 9!, 8!, 7!, ce

On est tent de complter le dbut de la factorielle qui se construit progressivement pour

10 9 8.

On remarque que pour obtenir

qui correspond en fait constante, gale

ni !. Ainsi si f0 n0 ! = 7!N !.

chaque tape on calcule

fi ni !,

il semble qu'on obtient une quantit

N < 7. Il s'agit maintenant de le i que i N, ni !fi = 7!N !. I la proprit est trivialement vraie pour i = 0. H soit i N, ni !fi = 7!N ! fi+1 ni+1 ! = 7!N ! ? Si ni > 7 alors ni+1 !fi+1 = (ni 1)!ni fi = ni !fi = 7!N ! ni+1 ! 7!N ! fi par l'hypothse de rcurrence. Sinon, ni+1 !fi+1 = ni+1 ! ni+1 = ni +1 ni ! = 7!N !. Ainsi la proprit voulue est bien initialise et hrditaire, elle est donc vraie sur tout N. On dduit de cet 7!N ! invariant qu' la n de l'algorithme on renvoie fi = ni avec ni = 7, donc l'algorithme 7 renvoie fi = N !.
On peut vrier sur un exemple que l'invariant semble aussi vri pour dmontrer. Montrons donc par rcurrence sur

2.2.2 Invariant et correction de l'algorithme 8


Excutons l'algorithme 8 pour (respectivement de

M = 48 m
et

et

N = 30,

n)

la

i-ime

excution de la boucle

tant que.

en appelant

mi

(respectivement

ni )

la valeur de

i 0 1 2 3 4 5

m 48 18 18 6 6 6

n 30 30 12 12 6 0

diviseurs communs

{1, 2, 3, 6} {1, 2, 3, 6} {1, 2, 3, 6} {1, 2, 3, 6} {1, 2, 3, 6} {1, 2, 3, 6} m


et

Un invariant semble tre que l'ensemble des diviseurs communs rithme, dmontrons-le. Supposons qu'il existe itration de la boucle diviseur commun de invariant on a

reste constant au cours de l'algo-

tant que. Alors mk+1 = mk nk = q(m


et

divisant

mk = m q

et

nk = n q ,

que mk > nk , et qu'il y a une k + 1-ime n ). nk+1 = nk = n q donc q est encore un reste constant appliquant cet

mk+1

k = 0 et k = h, h tant la dernire itration de la boucle tant que avant l'arrt de l'algorithme, {d N/d|M et d|N } = {d N/d|mh et d|0}. En considrant le maximum de ces ensembles, on obtient pgcd(M, N ) = pgcd(mh , 0) = mh , ce qui dmontre bien la correction de l'algorithme.

tout au long de l'algorithme, soit

nk+1 . Ainsi on a montr que l'ensemble des diviseurs communs {d N/d|mk et d|nk } constant pour tout k . En particulier en

Remarques :
Cet algorithme s'appelle l'algorithme de PGCD par dirences successives. On utilise classiquement l'algorithme d'Euclide, par divisions successives, pour calculer le PGCD. Eectivement l'algorithme par dirences 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

r3k )

la valeur de la variable

(respectivement

r1 , r2 , r3 )

la n de la

k -ime

itration de la boucle

tant que.

r1k , r2k ,

Pour

n=6: k 0 r3i r1i 0 r2i 1 i 0

1 2 3 4 5 0 1 1 2 3 1 1 2 3 5 1 2 3 5 8 1 2 3 4 5

6 5 8 13 6 r1i =
bo(i),

Ceci nous permet de supposer que peut procder de deux faons :

r2i =

bo(i + 1) et

r3i =

bo(i 1). Pour le dmontrer, on

Premire dmonstration : une habile rcurrence pour


Montrons par rcurrence sur

r1 ,

puis le reste.

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 + r2i1 = r1i + r1i1 = bo(i + 1). i
et donc On peut en dduire les deux autres ingalits :

Ainsi l'galit est initialise et hrditaire, elle est donc vraie pour tout

i N, r2i = r1i+1 =

bo(i

+ 1),

et

r1i = bo(i). i N , r3i = r1i1 =

bo(i

Seconde dmonstration : tout en mme temps, c'est plus facile.


Montrons par rcurrence sur

1),

et l'galit est aussi vraie pour

i = 0.

i que i N, r1i = bo(i), r2i = bo(i + 1), et r3i = bo(i 1). r11 = 1 = bo(1), r21 = 1 = bo(2), et r31 = 0 = bo(0). 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 prcdente et h.r.) donc r2i+1 = bo(i + 2). Ainsi les trois galits sont initialises et hrditaires, donc vraies pour tout i de N.

I H

au rang 1,

En n d'algorithme

i = n,

il faut donc renvoyer

r1 .

2.3

Sance 6 (26/10/2007)

2.3.1 Correction de l'algorithme de recherche squentielle en tableau tri


Donnes : T [1..N ] : tableau d'entiers tri dans l'ordre croissant, e : entier recherch dans le tableau Rsultat : renvoie Vrai si e est un lment du tableau T , Faux sinon.
Variable :

dbut

entier.

i 1;

tant que i N et T [i] < e faire n n renvoyer (i N


i i + 1;
et

T [i] = e);

Algorithme 7 : Recherche(d T [1..N ] : tableau, d e : entier) : boolen

L'invariant doit nous servir dmontrer la correction de l'algorithme, il y a plusieurs possibilits :   de

j [1, i 1], T [j] < e T [i 1] < e


la n de la

Dmontrons les trois et utilisons-les chacun pour dmontrer la correction de l'algorithme. Appelons ik la valeur

k -ime

itration de la boucle

tant que.

Invariant 1
Montrons par rcurrence sur

Initialisation : au rang k = 1, on a excut la boucle tant que une fois, donc on a bien T [1] = e.
11

que

k 1, j [1, ik 1], T [j] < e

k 1, j [1, ik 1], T [j] < e, et que la boucle tant que T [ik ] < e, donc en ajoutant cette ingalit celles de l'hyptohse de rcurrence on obtient k 1, j [1, ik ], T [j] < e. La proprit tant initalise et hrditaire, elle est vraie pour tout k 1, c'est dire si la boucle tant que
: supposons qu' un certain rang s'excute

Hrdit
k

fois. Alors au dbut de la

k -ime

itration on a bien test que

s'excute une fois ou plus. Prouvons maintenant la correction de l'algorithme. S'il renvoie trouv une case du tableau, la i-ime, qui contient l'un des deux termes de la conjonction est faux :  soit  soit

e.

S'il renvoie

Vrai, alors i N et T [i] = e, on a donc bien Faux, alors (i N et T [i] = e) est faux, donc

i > N , alors l'invariant dmontr arme qu'aucune des N cases du tableau ne contient e. i N et T [i] = e. L'algorithme s'est arrt, donc est sorti de la boucle, donc la condition de boucle T [i] < e n'tait pas vrie, donc T [i] > e. Or le tableau contient des entiers rangs par ordre croissant donc e n'est pas contenu dans la i-ime case ni aucune droite. D'autre part l'invariant nous arme directement que e n'est contenu dans aucune des i 1 premires cases. Finalement e n'est dans aucune des N cases du tableau.

On a donc bien dmontr que l'algorithme est correct.

Invariant 2
Au dbut

k -ime

itration de la boucle

tant que

on teste que

T [ik1 ] < e.

Or

ik1 = ik 1

d'aprs

l'algorithme, donc on a bien pour tout

k 1, T [ik 1] < e.

Prouvons maintenant la correction de l'algorithme. S'il renvoie trouv une case du tableau, la i-ime, qui contient l'un des deux termes de la conjonction est faux :  soit

e.

S'il renvoie

Vrai, alors i N et T [i] = e, on a donc bien Faux, alors (i N et T [i] = e) est faux, donc
case du tableau contient une valeur

i > N,

alors l'invariant dmontr arme que la

i 1-ime

infrieure strictement  soit

e,

or les cases prcdentes contiennent des valeurs strictement infrieures puisque

e n'est pas contenu dans le tableau. i N et T [i] = e. L'algorithme s'est arrt, donc est sorti de la boucle, donc la condition de boucle T [i] < e n'tait pas vrie, donc T [i] > e. Or le tableau contient des entiers rangs par ordre croissant donc e n'est pas contenu dans la i-ime 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 premires cases. Finalement e n'est dans aucune des N cases du tableau.
le tableau est rang dans l'ordre croissant, donc

On a donc bien dmontr que l'algorithme est correct. Remarquons que l'invariant 2 tait plus direct dmontrer (sans rcurrence), mais demande quelques lignes supplmentaires pour la preuve de correction. Lorsqu'on demande un invariant il est possible qu'il y ait plusieurs possibilits, il s'agit d'en choisir un qui soit susamment simple dmontrer et utiliser pour la preuve de correction. Prcisons aussi que l'invariant a t dmontr dans tous les cas o la boucle

une fois.

tant que est excute au moins


i1
premires cases

Ceci dit le cas o elle ne s'excute pas ne pose pas de problme, les preuves de correction restent

valides, on peut juste se dbarasser de ce qui suit le  qui ne sont alors pas dnies puisque

D'autre part

 (cela concerne les

i = 1).

2.3.2 Correction de l'algorithme de multiplication par additions successives


Donnes : m, n : entiers Rsultat : renvoie le produit mn. dbut
Variables :

p, i,

entiers.

n

n renvoyer p;

p 0 ; i 0; tant que i < n faire p p + m; i i + 1;

Algorithme 8 : Produit(d m, n : entiers) : entier

12

L'invariant est

p = mi.

Appelons

dmontrons par rcurrence sur

p1 = 0 = m 0 = mi0 . pk = mik pk+1 = mik+1 ? pk+1 = pk + m = mik + m = m(ik + 1) = mik+1 Ainsi la proprit est initialise et hrditaire, donc vraie pour tout k , et l'galit
invariant de l'algorithme.

I H

que

pk , ik , les pk = mik .

valeurs de

et

au dbut de la

k -ime

boucle

tant que

et

propose est bien un

2.3.3 Invariant de l'algorithme de recherche dichotomique modi


La seule modication de l'invariant demande concerne le cas d'galit. Dans le cours, l'algorithme renvoyait l'indice de la dernire case contenant

e,

dans l'exercice on veut rcuprer l'indice de la premire case contenant

e,

il sut donc de remplacer dans l'algorithme 

>e

par 

e .

13

Chapitre 3
Complexit

3.1

Sance 6 (26/10/2007)

3.1.1 Complexit de l'algorithme 14


Comme l'algorithme 14 contient une boucle d'itrations de cette boucle. Attention, lors du comptage, il faut tre prudent, et ventuellement vrier sur un exemple : si une variable

tant que, il s'agit de compter en fonction des donnes le nombre


i i + 1,
cela signie qu'il y a eu

passe au total par

valeurs direntes par l'aectation

n1

aectations

au total. Pour cet algorithme par exemple,

passe de 0

B,

il y a donc

2 + 2B

aectations,

multiplications et

additions, mais

B excutions de la boucle tant que, et B + 1 comparaisons (la dernire comparaison choue

et fait sortir de la boucle).

On peut proposer un algorithme plus ecace de calcul de puissance, c'est l'algorithme d'exponentiation rapide 1 , qui a une complexit de O(log B) multiplications au lieu de O(B) pour calculer AB . Vous pouvez vous

amuser en chercher un invariant pour dmontrer sa correction.

Donnes : A, B : entiers Rsultat : renvoie la puissance AB . dbut


Variables :

p, i, x,

entiers.

tant que i = 0 faire si i modulo 2 = 1 alors n


p p x; i i 1;

p 1; x A; i B ;

n

n renvoyer p;

x x x; i i/2;

Algorithme 9 : ExponentiationRapide(d A, B : entiers) : entier

1 http://fr.wikipedia.org/wiki/Exponentiation_rapide
14

Chapitre 4
Listes chanes

4.1

Sance 9 (14/11/2007)

4.1.1 Familiarisation avec les listes chanes


Si vous voulez rchir sur des listes chanes, n'hsitez pas essayer des ides d'algorithmes, ou excuter votre algorithme, sur de petits dessins du genre de ceux des gures 4.1.1, en vous rappelant que changer le successeur d'un lment, c'est simplement dcoller et recoller ailleurs la che qui sort de la case de droite de cet lment. (a) (b)

(c)

(d)

(e)

(f )

(g)

(h)

(i)

(j)

(k)

(l)

15

(m)

(n)

Fig. 4.1 

Utilisations de listes chanes : aprs la ligne 1 (a), 2 (b), 3 (c), 4 (d), 5 (e), rorganisa-

tion (f), aprs la ligne 6 (g), rorganisation (h), aprs la ligne 7 (i), 8 (j), 9 (k), rorganisation (l), aprs la ligne 10 (m), 11 (n).

4.2

Sance 10 (28/11/2007)

4.2.1 Algorithmes sur les listes chanes


Les algorithmes qui utilisent une liste chane passent la plupart du temps par l'opration consistant parcourir la liste chane, de la mme faon que les premiers exercices que nous avons vus sur les tableaux consistent parcourir le tableau. Pour ces derniers, la structure gnrale des algorithmes consistait donc initialiser une variable ou

i indiquant un numro de case 1, puis le faire varier l'aide d'une boucle pour tout tant que jusqu' un entier n correspondant au nombre de cases du tableau. Sur les listes chanes, le parcours peut se faire l'aide d'une boucle tant que comme illustr en gure 10

(on peut aussi eectuer le parcours par une fonction rcursive mais il est possible que ce soit plus dlicat).

Donnes : L, . . . : liste simplement chane, . . . Rsultat : renvoie un truc aprs avoir parcouru L. dbut
Variables :

Q,

liste simplement chane.

Q L;
...;

tant que Q = NULL faire


...;

QQ

succ;

n n

...;

...;

renvoyer . . . ; Algorithme 10 : TrucGrceAUnParcoursDeListe(L : liste simplement chane) : truc


Q=
NULL, ou en l'atteignant, c'est dire quand

Attention la condition d'arrt, on pourra prfrer s'arrter aprs avoir atteint le dernier lment, c'est dire quand

succ = NULL.

4.2.2 Adresse de la dernire cellule d'une liste


Donnes : L : liste simplement chane Rsultat : renvoie l'adresse de la dernire cellule d'une liste dbut
Variables :

Q,

liste simplement chane.

Q L;

tant que Q succ = NULL faire n n renvoyer L;


QQ
succ;

Algorithme 11 : DerniereCellule(L : liste simplement chane) : liste simplement chane


n est la taille de la liste (son nombre d'lments).

Quand ce n'est pas prcis dans les exercices sur les listes,

16

4.2.3 Premier lment mis la n d'une liste


Notons qu'on s'arrte avant d'tre arriv la n de la liste, c'est dire qu'on quitte la boucle ds qu'on atteint le dernier lment.

Donnes : L : liste simplement chane Rsultat : modie L pour dplacer son premier lment en dernire position
Variable :

dbut

Q,

liste simplement chane.

Q L; si Q = NULL

n tant que Q succ = NULL faire n n


QQ
succ succ;

alors renvoyer NULL;

crerListe(L

info, NULL);

Algorithme 12 : PremierALaFin(L : liste simplement chane) : liste simplement chane

4.2.4 Suppression de tous les lments de valeur donne d'une liste


Donnes : L : liste simplement chane, e : entier Rsultat : supprime de L tous les lments de valeur e dbut
Variable :

Q,

liste simplement chane.

Q L; si Q = NULL

n tant que Q succ = NULL faire si Q info = e alors n n n


Supprimer(L,Q); succ;

alors renvoyer NULL;

QQ

Algorithme 13 : SupprimeValeur(L : liste simplement chane, e : entier)


O(n),
donc SupprimeValeur a une complexit en

L'algorithme Supprimer vu en cours a une complexit en

0(n2 )
En utilisant une liste doublement chane, l'ide est que la suppression peut se faire en temps constant (comme on a alors accs l'adresse du dernier lment, il sut de faire pointer le successeur de cet lment vers le successeur de son successeur). Ainsi la complexit totale de SupprimeValeur en utilisant une liste doublement chane serait en

O(n).

4.3

Sance 11 (07/12/2007)

4.3.1 Suppression de tous les doublons d'une liste


L'ide de l'algorithme 14 est de stocker la valeur de la case prcdente pour la comparer avec la valeur de la case actuelle, mais si elles sont identiques la suppression par l'algorithme Supprimer se fait en une complexit totale de

O(n), c'est dire

O(n2 )

pour SupprimerDoublons. Il est possible de faire mieux avec l'algorithme 15

qui ne stocke pas la valeur de l'lment prcdent, mais carrment l'lment prcdent lui-mme, permettant d'atteindre une complexit en

O(n).

17

Donnes : L : liste simplement chane Rsultat : Modie L en supprimant tous ses doublons, c'est dire ses lments qui auraient mme
valeur que leur successeur

dbut

Variable :

Q,

liste simplement chane.

Q L; si L = NULL

alors tant que Q succ = NULL faire


valpred Q info; Q Q succ; si Q info = valpred Supprimer(Q,L);

alors

n

n

n

n

Algorithme 14 : SupprimeDoublons(L : liste simplement chane)

Donnes : L : liste simplement chane Rsultat : Modie L en supprimant tous ses doublons, c'est dire ses lments qui auraient mme
valeur que leur successeur

dbut

Variable :

Q,

liste simplement chane.

Q L; si L = NULL

alors tant que Q succ = NULL faire

n

n

n

n

P Q; Q Q succ; si Q info = P info alors P succ Q succ; //on supprime de L l'lment point par Q.

Algorithme 15 : SupprimeDoublons(L : liste simplement chane)

18

4.3.2 Miroir d'une liste


Donnes : L : liste simplement chane Rsultat : Renvoie une liste constitue des lments de L dans l'ordre inverse dbut
Variables :

Q, M ,

listes simplements chanes.

Q L; M L; si L = NULL alors M crerListe(L info,NULL); tant que Q succ = NULL faire Q Q succ; M crerListe(Q info,M );

n

n n renvoyer M ;

Algorithme 16 : Miroir(L : liste simplement chane) : liste simplement chane


en place,
c'est dire

On cherche modier l'algorithme 16 pour inverser une liste simplement chane

sans crer de nouvelle liste. Pour cela on va faire avancer le long de la liste trois pointeurs sur trois lments conscutifs de la liste modier, pour garder en mmoire leurs adresses et pouvoir faire les modications.

Donnes : L : liste simplement chane Rsultat : Modie L pour inverser l'ordre de ses lments dbut si L = NULL alors
Variables :

Q, R, S ,

listes simplement chanes.

n

n

n

Q L succ; L succ NULL; tant que Q = NULL S Q succ; Q succ L; L Q; Q S;

faire

Algorithme 17 : Miroir(L : liste simplement chane)

4.3.3 Concatnation de deux listes


L'ide est de parcourir la premire liste jusqu' son dernier lment et lui aecter comme successeur le premier lment de la seconde, comme montr dans l'algorithme 18.

4.3.4 Familiarisation avec les listes doublement chanes


L'ide d'une liste doublement chane est que chaque cellule, au lieu de contenir seulement un pointeur vers la cellule suivante, contient aussi un pointeur vers la cellule prcdente. Pour la structure de donnes utiliser il y a en fait un dtail technique supplmentaire : une sorte de "bloc d'adressage" qui contient l'adresse du premier lment de la liste et l'adresse du dernier lment. Ainsi, si est une liste doublement chane,

info est vide (NULL),

succ dsigne son premier lment,

dsigne son dernier lment, et pour rcuprer par exemple la valeur de son premier lment on

A A pred fait A succ

info. Quelles fonctions appliquer pour crer une liste doublement chane 2 lments, contenant les valeurs 4 et

6 ? Par exemple on peut procder comme dans l'algorithme 19.

19

Donnes : L1, L2 : listes simplement chanes Rsultat : renvoie L1 qui on a concatn L2 dbut si L = NULL alors renvoyer L2; n sinon
Q L;
Variable :

Q,

liste simplement chane.

tant que Q succ = NULL faire n n n


QQ
succ succ;

renvoyer L1;

L2;

Algorithme 18 : Concatne(L : liste simplement chane) : liste simplement chane

L crerTriplet(NULL,NULL,NULL); Q crerTriplet(L, 4, L); L succ Q; L pred Q; R crerTriplet(L pred, 6, L); Q succ R; L succ Q; L pred R;

Algorithme 19 : Cration d'une liste doublement chane 2 lments contenant 4 et 6.

Sur la liste doublement chane ainsi cre, comment supprimer le dernier lment pour obtenir une liste doublement chane 1 lment (contenant donc la valeur 4) ? Par exemple on applique l'algorithme 20.

L pred Q; Q succ L;

Algorithme 20 : Suppression du dernier lment de la liste cre prcdemment.

4.4

Exercices non corrigs en TD (28/12/2007)

4.4.1 Miroir d'une liste doublement chane


L'ide est de traiter tous les lments de la liste, y compris le bloc d'adressage, en inversant leur prdcesseur avec leur successeur. La complexit de l'algorithme 21 est donc en

O(n).

4.4.2 Concatnation de deux listes doublement chanes


L'ide de l'algorithme 22 est de corriger les pointeurs du bloc d'adressage de la premire liste, de son dernier lment, ainsi que du premier lment de la seconde liste. Le tout se fait en temps constant,

O(1).

20

Donnes : L : liste doublement chane Rsultat : Renvoie une liste constitue des lments de L dans l'ordre inverse dbut
Variables :

P , Q,

lments d'une liste doublement chane.

P L; Q L succ; si Q = NULL alors tant que Q = L P P


succ pred

//On traite l'lment P en inversant son successeur stock dans Q avec son prdcesseur:
P pred; Q; //On traitera Q, l'ancien successeur de P , la prochaine tape: P Q; Q Q succ;

faire

n

//Il reste traiter le dernier lment P de la liste, qui a pour successeur Q = L

n

n renvoyer L;

P P

succ pred

P Q;

pred;

Algorithme 21 : Miroir(L : liste doublement chane) : liste doublement chane

Donnes : L1, L2 : listes doublement chanes Rsultat : Renvoie une liste constitue des lments de L1 puis de ceux de L2 dbut si L1 succ = NULL alors renvoyer L2; n sinon si L2 succ = NULL alors renvoyer L1; n sinon
pred L1 succ L2 pred L2 pred; pred succ L1; renvoyer L1;
succ pred

L2 L1 L1 L1

pred;

succ;

n n Algorithme 22 : Concatene(L1, L2 : listes doublement chanes) : liste doublement chane

21

Chapitre 5
Arbres

5.1

Sance 12 (12/12/2007)

5.1.1 Familiarisation avec les arbres


Un arbre binaire est cod comme une cellule valeur

trois cases qui reprsente la racine de l'arbre, contient une

info, et un pointeur vers la cellule-racine de son sous-arbre gauche

sag, ainsi qu'un pointeur

vers la cellule-racine de son sous-arbre droit

sad. Les "nuds au bout des branches" (nuds de degr

1)

d'un arbre binaire sont appels feuilles, ils pointent vers NULL gauche et NULL droite. Pour parcourir une liste, on pouvait partir de la tte et suivre les pointeurs vers les successeurs jusqu' arriver la n de la liste et donc un pointeur vers NULL l'aide d'une boucle une boucle l'arbre. Comment crer un arbre de racine tiquete 2 ayant deux ls tiquets 1 et 3 ? crerArbre(2,crerArbre(1,NULL,NULL),crerArbre(3,NULL,NULL))

tant que. Avec un arbre utiliser tant que est beaucoup moins naturel, et on prfrera employer des algorithmes rcursifs : savoir

rsoudre un problme sur le sous-arbre gauche et le sous-arbre droit permettre de rsoudre le problme sur

5.1.2 Hauteur d'un arbre binaire


Ide
: la hauteur d'un arbre binaire est gale celle du plus haut des sous-arbres gauche et droit de sa racine, augmente de 1. Attention l'initialisation, les nuds isols (pointant sur NULL et NULL) sont des arbres de hauteur 0 !

Donnes : A : arbre binaire Rsultat : renvoie la hauteur de l'arbre A dbut si A = NULL alors renvoyer 0; n sinon si A sag = NULL et A sag = NULL alors renvoyer 0; n sinon renvoyer 1 + max Hauteur(A sag),Hauteur(A sad) ; n n Algorithme 23 : Hauteur(A : arbre binaire) : entier

5.1.3 Nombre de feuilles d'un arbre binaire


Ide : le nombre de feuilles d'un arbre binaire est gale la somme du nombre de feuilles des sous-arbres
gauche et droit de sa racine.

22

Donnes : A : arbre binaire Rsultat : nombre de feuilles de l'arbre A dbut 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
5.2 Sance 13 (12/12/2007, 13/12/2007)

5.2.1 Intermde complexit


Attention ne pas utiliser des fonctions inutiles. Par exemple, si vous parcourez un arbre et qu' chaque noeud vous appelez une fonction de calcul de hauteur d'arbre, cette dernire tant de complexit linaire en la taille de l'arbre, votre algorithme global sera dj au moins de complexit quadratique. Pour valuer la complexit d'un algorithme rcursif sur un arbre, vous serez peut-tre amens vous interroger sur son nombre de noeuds arbre a

n,

son nombre d'artes

a,

ou son nombre de feuilles

f.

Retenez que si un

feuilles, son nombre de noeuds et son nombre d'artes sont en

(n).

Dtaillons quelques formules qui

permettent de le dmontrer, ainsi que les petits raisonnements qui permettent de les retrouver. Tout noeud sauf la racine a un pre, on peut donc lui associer l'arte qui vient sur lui. Ainsi, on dnit une bijection entre tous les noeuds sauf la racine avec toutes les artes. Donc pour tout arbre. Pour la formule sur le nombre de feuilles, on va se restreindre aux arbre strictement binaires, c'est dire ceux dont aucun noeud interne n'a qu'un ls, en remarquant qu'ils peuvent se construire de la faon suivante. On initialise l'arbre un noeud isol ( la fois racine et feuille). Puis on applique la rgle suivante : on choisit une feuille, on lui accroche deux feuilles (une " une feuille pour en ajouter deux, donc comme

a = n 1.

Cette formule est valable

cerise ").

Appelons

noeuds (respectivement, d'artes, de feuilles) aprs l'ajout de la

nk k -ime

(respectivement

ak , fk ),

le nombre de Ainsi,

cerise. A l'ajout d'une cerise, on enlve

fk+1 = fk + 1.

De plus on ajoute deux artes donc

a1 = 2

et

f1 = 2

on peut montrer par rcurrence que

ak = 2k

et

fk = k + 1 ,

donc

ak+1 = ak + 2. ak = 2fk 2.

Finalement pour tout arbre strictement binaire on a :

a = n 1 = 2f 2
Ainsi, on a bien

a = O(n)

et

f = O(n).

5.2.2 Nombre de nuds de profondeur xe d'un arbre binaire


Ide : le nombre de nuds de profondeur p d'un arbre binaire est gale la somme du nombre de nuds
de profondeur

p1

dans le sous-arbre gauche de sa racine avec le nombre de nuds de profondeur

p1

dans

le sous-arbre droit de sa racine.

5.2.3 Eeuillage d'un arbre binaire


Ide : le nombre de nuds de profondeur p d'un arbre binaire est gale la somme du nombre de nuds
de profondeur

p1

dans le sous-arbre gauche de sa racine avec le nombre de nuds de profondeur

p1

dans

le sous-arbre droit de sa racine.

23

Donnes : A : arbre binaire, p : entier Rsultat : renvoie le nombre de nuds de profondeur p de l'arbre A dbut si p = 0 et A = NULL alors renvoyer 1; n sinon si A = NULL alors renvoyer 0 n sinon renvoyer NombreNudsProfondeur(A sag, p 1)+NombreNudsProfondeur(A sad, p 1); n n Algorithme 25 : NombreNudsProfondeur(A : arbre binaire, p : entier) : entier

Donnes : A : arbre binaire Rsultat : modie A en l'eeuillant dbut si A saq = NULL et A sad = NULL alors
A
NULL

n si (A sag = NULL) alors si (A sag sag = NULL) et (A sag sad = NULL) alors n sinon n
A
sag

// cas o l'arbre de dpart est une racine-feuille

NULL

// suppression du ls gauche de A, qui est une feuille ;

Eeuille(A

sag );

n si (A sad = NULL) alors si (A sad sag = NULL) et (A sad sad = NULL) alors n sinon n n
A
sad

NULL

// suppression du ls droit de A, qui est une feuille ;

Eeuille(A

sad);

n

Algorithme 26 : Eeuillage(A : arbre binaire) : entier

24

Chapitre 6
Autres structures de donnes

6.1

Sance 14 (14/12/2007)

6.1.1 Notation postxe d'un arbre


Encore un algorithme rcursif assez simple : la notation postxe d'un arbre, c'est celle de son sous-arbre gauche, suivie de celle du droit, suivie de l'tiquette de sa racine ! Attention toutefois, la concatnation se fait en temps linaire par rapport la taille de la liste en parallle. Cette opration peut donc tre eectue un nombre linaire de fois par rapport la taille de l'arbre, ce qui donne l'algorithme 27 une complexit totale quadratique en la taille de l'arbre en entre.

Donnes : A : arbre Rsultat : Renvoie une liste contenant la notation postxe correspondant l'arbre A dbut si A = NULL alors renvoyer NULL; n sinon si A sag = NULL et A sad = NULL alors renvoyer crerListe(A info,NULL); n sinon si A sag = NULL alors renvoyer Concatner Postxe(A sad),crerListe(A info,NULL) ; n sinon si A sad = NULL alors renvoyer Concatner Postxe(A sag),crerListe(A info,NULL) ; n sinon renvoyer Concatner Postxe(A sad),Concatner(Postxe(A sad),crerListe(A n n
info,NULL)) ;

n

Algorithme 27 : Postxe(A : arbre) : liste simplement chane

6.1.2 Pile pour l'valuation d'une expression postxe


Ide de l'algorithme 28 : on dpile le premier lment de l'expression qui est stocke dans une pile. Si
c'est un symbole binaire (de noeud interne), on va rcursivement traiter deux fois le reste de la pile, rcuprer ainsi deux valeurs et eectuer leur opration par le symbole binaire. Si c'est un entier, on se contente de renvoyer la valeur de l'entier.

25

Donnes : P : pile contenant une notation postxe dont le dernier lment est en haut de la pile Rsultat : Renvoie la valeur de l'expression dont la notation postxe est stocke dans P dbut si PileVide?(P ) alors renvoyer 0; n sinon
Variables :

R1, R2

: entiers,

operation

: symbole.

n

n

n sinon renvoyer operation; //operation est alors un entier. n Algorithme 28 : Evaluer(P


: pile) : entier

operation sommetPile(P ); dpiler(P ); si operation = + ou operation = alors R1 Evaluer(P ); //P est alors modie ! R2 Evaluer(P ); renvoyer R1 operation R2;

6.1.3 File pour un parcours en largeur d'arbre


Ide de l'algorithme 29 :
ajouter la le le noeud racine, puis tant qu'il reste des lments dans la le, enlever le premier lment de la le, et ajouter ses ls en n de le. Ainsi, tout au long de l'algorithme, la le est constitue d'un ensemble (ventuellement vide) de noeuds d'une certaine profondeur ensemble (ventuellement vide) de noeuds de profondeur (

Breadth-First Search

k + 1,

ce qui est le principe du

parcours en largeur

k,

suivi d'un

en anglais). Cet algorithme a une complexit linaire en la taille de l'arbre parcourir.

6.1.4 Taille de l'intersection de deux tableaux d'entiers


Dans tous les cas, pour calculer la taille de l'intersection de lment apparaissant dans de la liste.

T1

et

T 2,

on va mettre dans une liste tout

T1

et

T 2,

puis supprimer les doublons de la liste si besoin, et enn calculer la taille

Ide de l'algorithme 30 : pour chacun des m lments du premier tableau, on regarde en O(n) s'il est
n
lments du second tableau (si oui on l'ajoute une liste d'lments de l'intersection des

prsent parmi les

deux tableaux). La complexit totale de cette tape est de

O(mn).

Il faut alors calculer liminer les doublons,

c'est dire des lments gaux du premier tableau qui appartiendraient aussi au second, ou inversement. Pour cela on utilise en particulier l'algorithme 13 pour la fonction calculer la taille de la liste en tableau, on regarde en donc en

SupprimeValeur. La complexit de cette tape


O(m + mn).
2

est quadratique en la taille de la liste d'lments de l'intersection des deux tableaux, c'est dire

O(m2 ). Il reste

Ide de l'algorithme 31 avec un des deux tableaux tri : pour chacun des m lments du premier
O(log n)
s'il est prsent parmi les lments du second tableau qui sont tris (le tri du

O(m).

Finalement la complexit totale est donc

tableau s'est fait avec une complexit en

O(m log n + n log n),

c'est dire

O(n log n)), par dichotomie. La complexit O(max(m, n) log n), (et O(m log n) si on

totale de cette tape est considre que le second

tableau est dj tri) elle est meilleure qu'avec l'ide prcdente. Attention toutefois la procdure de suppression des doublons que j'ai opportunment omise. Si on la ralise, sa complexit est en complexit de second en

Ide de l'algorithme 32 avec les deux tableaux tris : on trie le premier tableau en O(m log m), le

O(m2 ), O(m + m log n).


2

ce qui pour rpondre prcisment la question pose nous donne une

O(n log n), puis on parcourt simultanment les deux tableaux. La complexit totale est en O(n log n+ m log m + m + n), soit O(max(m, n) log max(m, n)), ce qui est encore meilleur que l'ide prcdente. Si en plus on considre que les tableaux sont dj tris, on obtient alors une complexit en O(m + n).

26

Donnes : A : arbre Rsultat : Renvoie une liste chane correspondant au parcours en largeur de A dbut
Variables :

L,

liste chane,

F,

le.

L NULL; F crerFile; si A = NULL alors ajouterFile(F, A);

tant que non FileVide?(F ) faire


A tteFile(F ); retirerFile(F ); L
crerListe(A

//On traite le premier lment de la le :

info,L);

//On ajoute la n de la le les ls ventuels, traiter plus tard : si A sag = NULL alors

n n

n

ajouterFile(F, A sag); n si A sad = NULL alors ajouterFile(F, A sad); n

//La liste L a t construite dans le mauvais sens, son premier lment est celui visit en dernier, //donc de profondeur maximale dans A :

renvoyer Miroir(L);

Algorithme 29 : ParcoursLargeur(F

: le) : liste simplement chane

27

Donnes : T 1, T 2 : tableaux de respectivement m et n entiers Rsultat : Renvoie le nombre d'entiers prsents dans les deux tableaux.
Variables :

dbut

L,

liste chane ;

t,

entier.

pour i de 1 m faire
j 1;

NULL;

tant que j < n et T 1[i] = T 2[j] faire n si j < n alors n n


L j j + 1;

//T 1[i] = T 2[j] donc on ajoute T 1[i] L :


crerListe(T 1[i], L);

//limination des doublons de L :


Q L;

tant que Q = N U LL faire


supprimeValeur(Q succ;

succ,Q

info);

n

QQ

//Taille de la liste L :
Q L; t 0;

tant que Q = N U LL faire n renvoyer t;


t t + 1; Q Q succ;

n

Algorithme 30 : TailleIntersectionNaif(T 1, T 2 : tableaux) : entier

Donnes : T 1, T 2 : tableaux de respectivement m et n entiers, T 2 est tri Rsultat : Renvoie le nombre d'entiers prsents dans les deux tableaux.
Variables :

dbut

L,

liste chane ;

t,

entier.

pour i de 1 m faire si RechercheDicho(T 2,T 1[i]) alors n n


L
crerListe(T 1[i], L);

NULL;

//limination des doublons de L :


Q L;

tant que Q = N U LL faire


supprimeValeur(Q succ;

succ,Q

info);

n

QQ

//Taille de la liste L :
Q L; t 0;

tant que Q = N U LL faire n renvoyer t;


t t + 1; Q Q succ;

n

Algorithme 31 : TailleIntersection1Tri(T 1, T 2 : tableaux) : entier


28

Donnes : T 1, T 2 : tableaux tris de respectivement m et n entiers Rsultat : Renvoie le nombre d'entiers prsents dans les deux tableaux.
Variables :

dbut

d, t,

entier.

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] = d alors

//T 1[i] n'a pas encore t trouv dans T 1 et T 2 :


t t + 1; //d contient le dernier lment trouv la fois dans T 1 et T 2 : d T 1[i];

n

n sinon si T 1[i] < T 2[j] alors n sinon n


i i + 1;

i i + 1; j j + 1;

j j + 1;

n

n renvoyer t; Algorithme 32 : TailleIntersection2Tris(T 1, T 2 : tableaux) : entier

29

Vous aimerez peut-être aussi