Vous êtes sur la page 1sur 35

Correction des TD d'algorithmique de L2

U.E. FLIN 301 - 2008/2009

Philippe Gambette
5 juin 2009

Table des matires

Table des matires 1 Rvisions, preuves d'arrt


1.1 Sance 1 (29/09/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.1 1.1.2 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.3 1.3.1 1.3.2 1.3.3 1.3.4 Algorithme 1 - PlusProche Algorithme 2 - Somme? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 3
3 3 4 4 4 4 4 6 6 6 7 7 7

Sance 2 (01/10/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mthodologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Algorithme 3 - SSTableauVide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Algorithme 4 - LignesEgales? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Algorithme 5 - InsrerTabTri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mthodologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Preuve d'arrt de l'algorithme 6 Preuve d'arrt de l'algorithme 7 Preuve d'arrt de l'algorithme 8

Sance 3 (02/10/2008 ou 21/10/2008)

2 Invariants
2.1 Sance 4 (08/10/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 2.1.2 2.1.3 2.2 2.3 2.2.1 2.3.1 2.3.2 Les invariants, quoi a sert ? Invariants de l'algorithme 15 Invariants de l'algorithme 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9
9 9 9 10 11 11 12 12 12

Sance 5 (13/10/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Invariant et correction de l'algorithme 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . Correction de l'algorithme 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Correction de l'algorithme de recherche squentielle en tableau tri . . . . . . . . . . . . Sance 6 (15/10/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Complexit d'algorithmes
3.1 Sance 7 (20/10/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 3.1.2 3.1.3 3.2 3.2.1 3.2.2 3.2.3 3.2.4 3.3 3.3.1 3.3.2 3.4 3.4.1 3.4.2 3.4.3 3.5 3.5.1 Mthodologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Complexit de l'algorithme 15 (exercice 1) . . . . . . . . . . . . . . . . . . . . . . . . . . Complexit de l'algorithme 16' (exercice 3 complexit) . . . . . . . . . . . . . . . . . . . Arrt et complexit de l'algorithme 12 (exercice 2 complexit) . . . . . . . . . . . . . . . Arrt et complexit de l'algorithme 13 (exercice 2 invariants) . . . . . . . . . . . . . . . Arrt et complexit de l'algorithme 9 (exercice 3 arrt) . . . . . . . . . . . . . . . . . . . Complexit de la recherche dichotomique (exercice 3 algorithme et preuves) . . . . . . . Algorithme indicePrdcesseur (exercice 4 algorithme et preuve) . . . . . . . . . . . . .

14
14 14 14 14 15 15 15 15 16 16 16 16 17 17 17 18 18 18

Sance 8 (22/10/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Sance 9 (03/11/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Test de tri d'un tableau (exercice 4 complexit) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Algorithme d'valuation d'un polynme (exercice 5 complexit) . . . . . . . . . . . . . . Algorithme de plus long prxe suxe (exercice 7 complexit) Exponentiation rapide (exercice 6 complexit) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exponentiation rapide - version rcursive (exercice 6 complexit) . . . . . . . . . . . . .

Sance 10 (05/11/2008)

Sance 11 (12/11/2008)

3.5.2

Problme SomMax (complexit)

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

18

4 Listes chanes
4.1 Sance 12 (17/11/2008) 4.1.1 4.1.2 4.1.3 4.2 4.2.1 4.2.2 4.3 4.3.1 4.3.2 4.3.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Algorithmes sur les listes chanes Familiarisation avec les listes chanes

22
22 22 22 22 23 23 23 26 26 26 26

Adresse de la dernire cellule d'une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Premier lment mis la n d'une liste

Sance 13 (19/11/2008)

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

Sance 14 (26/11/2008)

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

Suppression de doublons conscutifs d'une liste . . . . . . . . . . . . . . . . . . . . . . . Concatnation de deux listes simplement chanes Concatnation de deux listes doublement chanes

5 Arbres
5.1 5.2 Fin de la sance 14 (26/11/2008) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 5.2.1 5.2.2 5.2.3 Familiarisation avec les arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hauteur d'un arbre binaire Sance 15 (03/12/2008)

28
28 28 28 28 28 29

Nombre de feuilles d'un arbre binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eeuillage d'un arbre binaire

6 Tris
6.1 Sance 16 (10/12/2008) 6.1.1 6.1.2 6.2 6.2.1 6.2.2 6.2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Taille de l'intersection de deux tableaux d'entiers . . . . . . . . . . . . . . . . . . . . . . Test de l'existence de doublons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

30
30 30 32 32 32 32 32

Sance 17 (17/12/2008)

Tri par fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tri de notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tri par base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Avertissement
Ce document peut contenir des erreurs, indiquez-les moi

gambette@lirmm.fr (ceci pourrait vous permettre

de gagner un bonus pour la note de participation). 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. Les cours d'algorithmique de L1 sont disponibles sur l'espace pdagogique (unit FLIN 101).

AT X pour que vous puissiez participer la rdaction 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.

Chapitre 1
Rvisions, preuves d'arrt

1.1

Sance 1 (29/09/2008)

1.1.1 Algorithme 1 - PlusProche


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


Tant que.

: entier)

On pouvait aussi procder en utilisant une boucle variable de boucle, et l'incrmenter chaque itration.

Dans ce cas, attention bien initialiser la

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]|. P P T [1]; i 2; tant que i n faire si |x T [i] < |x P P | i i + 1;

et

i 1, n

alors P P

T [i];

n

n

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

: entier)

Pensez vrier votre algorithme sur un exemple si vous avez le temps. Vous devez aussi tre capable de le dcrire en quelques phrases, par exemple pour celui-l : on parcourt les cases du tableau en gardant en mmoire chaque tape le meilleur lment trouv jusqu' maintenant pour le comparer avec l'lment de la case courante. Remarquez aussi que la condition remplaant cette condition par

|x T [i] < |x P P |

assure qu'on renverra le premier lment du tableau

qui rpond la question. On aurait pu renvoyer le dernier lment du tableau qui rpond la question en

|x T [i] |x P P |.

1.1.2 Algorithme 2 - Somme?


En considrant que

renvoyer permet de terminer l'algorithme en arrtant les boucles en cours, une solution

est propose dans l'algorithme 3

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 3 : Somme?(d A[1..n] : tableau d'entiers, d B [1..n] : tableau d'entiers, d Som : entier)
boolen

1.2

Sance 2 (01/10/2008)

1.2.1 Mthodologie
On vous demande un algorithme que vous ne savez pas comment crire ? Prenez un exemple et tentez de voir intuitivement dessus comment rsoudre le problme. Tentez alors de gnraliser ces oprations pour obtenir les principes gnraux de votre algorithme. Puis traduisez ces principes en pseudo-code, le langage utilis pour dcrire un algorithme. Si besoin, quand vous cherchez les principes de base de votre algorithme, dcomposez le problme en sousproblmes que vous traitez indpendamment, comme pour l'algorithme

LignesEgales?.

1.2.2 Algorithme 3 - SSTableauVide


Faire un dessin de ce tableau double entre de boolens (c'est dire un matrice boolenne) peut tre utile pour visualiser le problme demand. On indiquera sur le tableau les valeurs l1 , l2 , parcourir le sous-tableau (i et

c1 , c2 (ck

indique bien

sr un numro de colonne, et lk un numro de ligne) ainsi que la progression des variables qui permettent de

dans l'algorithme 4).

Donnes : T [1..n, 1..n] un tableau de boolens, l1 , l2 , c1 , c2 Rsultat :


1 c1 c2 n. Renvoie Vrai si le Faux sinon.
sous-tableau

quatre entiers tels que

1 l1 l2 n

et

T [l1 ..l2 , c1 ..c2 ]

est vide (toutes les cases sont

Faux),

renvoie

dbut pour tous les i de l1 l2 faire pour tous les j de c1 c2 faire si T [i, j ] alors renvoyer Faux; n n renvoyer Vrai; n Algorithme 4 : SousTabVide?(d T [1..n, 1..n] : tableau d'entiers, d l1 , l2 , c1 , c2

: entiers) : boolen

1.2.3 Algorithme 4 - LignesEgales?


la colonne

T [1..n, 1..n] j.

est un tableau double entre rempli de Vrai ou Faux,

T [i, j ]

reprsente l'entier la ligne

et

Si vous ne voyez pas comment procder, vous pouvez dcomposer votre algorithme LignesEgales? en :

 un algorithme

CoupleLignesEgales?

(algorithme 5) qui teste si deux lignes donnes, la

i-ime

et la

j -ime,
rithme

 un algorithme

LignesEgales1? (algorithme 6) qui, pour tout couple de lignes direntes, appelle l'algoCoupleLignesEgales?.

sont gales.

Donnes : T [1..n, 1..n] un tableau de 0 et de 1, i et j deux entiers tels que 1 i n et 1 j n Rsultat : Renvoie Vrai si et seulement si les lignes i et j de T sont identiques, c'est dire ssi dbut tant que k n et T [i, k] = T [j, k] faire si k = n alors renvoyer Vrai; sinon n renvoyer Faux; n
k k + 1; k 1, n
,

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

n Algorithme 5 : CoupleLignesEgales?(d T [1..n, 1..n] : tableau d'entiers, i : entier, j


Remarquez que la boucle s'aperoit que la

: entier ) : boolen

Tant que de l'algorithme CoupleLignesEgales? permet de l'arrter ds qu'on Pour : pour k de 1 n, si T [i, k] = T [j, k]. . . .
i
et

k -ime

case est dirente dans les lignes

j,

contrairement la solution moins lgante

mais plus simple qui aurait consist utiliser une boucle

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 1 faire pour tous les j de i + 1 n faire si CoupleLignesEgales?(T, i, j ) alors renvoyer Vrai; n n n renvoyer Faux; n Algorithme 6 : LignesEgales1?(d T [1..n, 1..n] : tableau d'entiers) : boolen
Remarquez dans l'algorithme

i = j 1, n / k 1, n

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

LignesEgales1? les valeurs parcourues par les variables i et j

: ceci permet

(i, j ) tels que i < j . On vite donc de tester si la ligne j = 1 est gale la ligne i = 2 aprs avoir test si la ligne i = 1 est gale la ligne j = 2. Cela permet donc de faire en gros deux fois moins d'tapes que la solution plus simple mais moins lgante suivante : pour tout i de 1 n, pour tout j de 1 n, si i = j alors . . .
en fait d'atteindre toutes les valeurs des couples Une fois que vous avez trouv les deux algorithmes permettant de rsoudre chaque partie dcompose du problme, vous pouvez les runir dans l'algorithme 7, en faisant bien attention au fait que stoppe l'algorithme (et donc il ne faut pas rcrire dans

CoupleLignesEgales?). Pour approfondir : remarquons que comme il y a trois boucles (deux pour et une tant que imbriques,
suivante : trier les lignes du tableau en

renvoyer LignesEgales? le "renvoyer Faux" de l'algorithme


peut en obtenir un en

la complexit de l'algorithme 4 propos est en

O(n3 ). On O(n log n) (chaque


2

O(n2 log n)

de la manire

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 reprsentant contient seulement des 0 et des 1) et en commenant par trier

Faux

par 0 et

Vrai

par 1 (ainsi le tableau

par un tri par base (aussi appel tri radix, voir

algorithme 41), avant de comparer chaque ligne avec la suivante, pour obtenir une complexit totale en

O(n2 ).

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 1 faire pour tous les j de i + 1 n faire
k 1; i = j 1, n / k 1, n
,

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

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


k k + 1;

n

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

n

1.2.4 Algorithme 5 - InsrerTabTri


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 tri d'entiers. 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 8 : InsrerTabTri(dr T [1..n] : tableau d'entiers, d m : entier, d e : entier)

1.3

Sance 3 (02/10/2008 ou 21/10/2008)

1.3.1 Mthodologie
Quand on vous demande de prouver l'arrt d'un algorithme, vous pouvez avoir l'impression qu'on peut le justier en dcrivant la partie de l'algorithme qui concerne l'arrt. Le problme est que vous paraphrasez gnralement l'algorithme avec force priphrases. Il est impossible de voir si vous avez vraiment compris dans le cas o vos explications seraient embrouilles. Bref, pour viter cela, il existe une mthode formelle que vous devez appliquer. Il s'agit de construire (ou d'identier) une expression calcule partir des variables de l'algorithme, qui dcrot strictement tout au long de l'algorithme, et qui est valeurs entires et positives. Cette expression n'apparat pas ncessairement parmi celles calcules dans l'algorithme, il vous faudra parfois jongler avec les variables et des additions, soustractions, multiplications, fractions, valeurs absolues, etc., pour construire cette expression. Une fois que vous avez trouv une bonne expression candidate. Appelons

uk

la valeur de cette expression

la

k -ime

itration de l'algorithme. Il faut montrer qu'elle vrie bien les proprits demandes. Le fait qu'elle

est valeurs dans  soit en  soit, si Si

dcoule le plus souvent directement de la dnition. Pour la dcroissance stricte, il s'agit existe, alors

de montrer que si la

k + 1-ime itration de l'algorithme montrant uk+1 uk < 0 uk > 0, en montrant que uk+1 /uk < 1, ce

uk+1 < uk ,

ce que l'on fait :

qui peut tre plus facile dans certains cas (si

uk

est

dni avec des multiplications ou divisions par exemple).

uk

est bien une expression valeurs entires positives qui dcrot strictement chaque pas (= intration)

de l'algorithme, on est certain que l'algorithme ne peut avoir un nombre de pas illimit, c'est dire qu'il a un nombre de pas limit, et donc qu'il s'arrte. Pour nir, remarquons que pour dsigner l'expression strictement dcroissante valeurs entires, nous utilisons le formalisme des suites. La premire tape de votre preuve d'arrt (de mme que les preuves d'invariants du chapitre suivant) sera donc toujours de dduire de l'algorithme des relations sur la valeur des variables au

k + 1-me

pas en fonction du

k -ime.

Pour toute variable

x,

vous appelez donc

xk

sa valeur la n du

pas. Puis vous utiliserez les aectations de l'algorithme pour exprimer la relation entre si chaque pas, la seule instruction concernant proprit sur la suite  

est :

si x>0 alors xx-1,

k -ime xk +1 et xk . Par exemple

vous traduisez et obtenez cette

(xk )k0 : si xk > 0 alors xk+1 = xk 1 sinon, xk+1 = xk (ne pas oublier

a !)

1.3.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.3.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 ne peut prendre qu'un nombre ni de valeurs, donc l'algorithme s'arrte. Calculer le rsultat de l'algorithme 7 sur plusieurs exemples permet de remarquer qu'il calcule prouverons plus loin en utilisant un invariant.

N !.

Nous le

1.3.4 Preuve d'arrt de l'algorithme 8


Donnes : N, M N Rsultat : renvoie pgcdN, M . Variables : n, m entiers dbut tant que n = 0 et m = 0 faire si m > n alors sinon n
mmn nnm n N; m M;

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

n

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


nk
et : entier) : entier

En notant

mk
et

les valeurs respectives de

et

la

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

k -ime itration de la boucle tant que, n et m en galits mathmatiques sur

on les

(nk )

(mk ).
7

Lignes 3 : n N ; m M ;

n0 = N , m0 = M . mk+1 = mk nk Lignes 5 et 6 : m m n donne : k, mk > nk nk+1 = nk mk+1 = mk Lignes 7 et 8 : n n m donne : k, mk nk nk+1 = nk mk


donne : 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,

entier.

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 ne peut donc prendre qu'un nombre ni de valeurs, donc l'algorithme s'arrtera. On montre similairement que l'expression

mn

est aussi dcroissante strictement et valeurs dans

N.

Chapitre 2
Invariants

2.1

Sance 4 (08/10/2008)

2.1.1 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

rcurrence qu'il faut eectuer pour montrer que l'invariant est valable chaque tape. Prcisons qu'une dmonstration par rcurrence permet de montrer qu'une proprit tout

P (k )

est valable pour

de

N.

Or si l'on parle de la

k -ime

itration, ou boucle, d'un algorithme, on n'est pas sr qu'elle existe,

l'algorithme s'est peut-tre arrt avant d'arriver sa faudrait dire que la proprit

P (k )

est valable pour tout

k -ime boucle. k de N tel


de

Bref, pour tre totalement rigoureux, il que la

k -ime

itration de l'algorithme

est eectue. Nous abrgerons (et vous tes autoriss, et mme encourags, pour ne pas perdre de temps et surcharger vos copies, le faire) en valable pour tout Rappelons que pour dmontrer une galit

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

A=B

(respectivement, une ingalit

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

C'est mme trs fortement conseill pour viter des rdactions douteuses voire compltement fausses. . .

2.1.2 Invariants de l'algorithme 15


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 ?
Montrons l'invariant Pour cela appelons (respectivement

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.
boucle

Soit Mk la valeur de la variable M la k -ime 2 k N, Mk = N Ik . 2 2 I au rang 0, M0 = N = N 0 = N I0 .

tant que.

Montrons par rcurrence sur

que

soit

2 2 k N, Mk = N Ik Mk+1 = N Ik +1 ? 2 2 Mk+1 (N Ik +1 ) = Mk Zk N (Ik + 1)


(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.3 Invariants de l'algorithme 13


Appelons

Ai

(respectivement

i-ime
I H

itration de la boucle au rang 0, soit

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

Bi , Ci , Zi )

la valeur de la variable

(respectivment

B, C , Z )

la n de la

A0 = 1 = 3(X X ) + 1 = 3(X C0 ) + 1. i N, Ai = 3(X Ci ) + 1 Ai+1 = 3(X Ci+1 ) + 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)

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

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

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

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

au rang 0,

i que i N, Zi = (X Ci )3 . Z0 = 0 = (X X )3 = (X C0 )3 .

10

soit

i N, Zi = (X Ci )3 Zi+1 = (X Ci+1 )3 ?
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 (13/10/2008)

2.2.1 Invariant et correction de l'algorithme 8


Excutons l'algorithme 8 pour (respectivement de

i 0 1 2 3 4 5

m 48 18 18 6 6 6

n 30 30 12 12 6 0

Un invariant Appelons la n de la et vice versa.

M = 48 et N = 30, en appelant mi (respectivement ni ) i-ime excution de la boucle tant que. diviseurs communs m et n {1, 2, 3, 6} {1, 2, 3, 6} {1, 2, 3, 6} {1, 2, 3, 6} {1, 2, 3, 6} {1, 2, 3, 6} semble tre que l'ensemble des diviseurs communs m et n reste constant au n)
la n de la

la valeur de

cours de l'algo-

rithme, dmontrons-le.

Dk = {d N/d|mk et d|nk } l'ensemble des diviseurs communs aux valeurs des variables m et n k -ime itration de la boucle tant que. On cherche donc montrer que k N, Dk = Dk+1 .

Rappelons que pour montrer une galit d'ensemble, il faut montrer que tout lment de l'un est dans l'autre, Supposons qu'il existe q Dk , c'est dire q vriant : m , n N tels que mk = m q et nk = n q . Si mk > nk , alors mk+1 = mk nk = q (m n ). nk+1 = nk = n q donc q est encore un diviseur commun de mk+1 et nk+1 . On a le mme rsultat si mk nk . Donc dans tous les cas, q Dk+1 Inversement, considrons q Dk+1 . Alors m , n N tels que mk+1 = m q et nk+1 = n q . Si mk > nk , alors n q = nk+1 = nk donc nk est aussi divisible par q . De plus, m q = mk+1 = mk nk donc mk = m q + nk = m q + n q = (m + n )q donc mk est aussi divisible par q . La preuve fonctionne de faon symtrique pour le cas mk < nk . Finalement, dans tous les cas, q Dk . Ainsi on a montr que l'ensemble des diviseurs communs reste constant tout au long de l'algorithme, soit Dk constant pour tout k . En particulier en appliquant cet invariant k = 0 et k = h, h tant la dernire itration de la boucle tant que avant l'arrt de l'algorithme, on a {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.

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).

11

2.3

Sance 6 (15/10/2008)

2.3.1 Correction de l'algorithme 11


Rappelons que la suite de Fibonacci est dnie par rcurrence de la faon suivante :  bo(0)=0  bo(1)=0  bo(i)=bo(i

1)+bo(i 2) i
(respectivement

On commence par voir sur un exemple ce que calcule l'algorithme, en appelant ik (respectivement

r3k )

la valeur de la variable

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, r1 = 1 = bo(1). 1 H soit i N, k i, r1 = bo(k ) r1i+1 = bo(i + 1) ? k 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
I

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). H soit i N, r1 = bo(i), r2 = bo(i + 1), et r3 = bo(i 1) r1 i i i i+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.
au rang 1, En n d'algorithme

i = n,

il faut donc renvoyer

r1 .

2.3.2 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 10 : 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.

12

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. Hrdit : supposons qu' un certain rang k 1, j [1, ik 1], T [j ] < e, et que la boucle tant que
k
fois. Alors au dbut de la

que

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

s'excute

k -ime

itration on a bien test que

ingalit celles de l'hyptohse de rcurrence on obtient La proprit tant initalise et hrditaire, elle est s'excute une fois ou plus.

T [ik ] < e, donc en ajoutant cette k 1, j [1, ik ], T [j ] < e. vraie pour tout k 1, c'est dire si la boucle tant que

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).

13

Chapitre 3
Complexit d'algorithmes

3.1

Sance 7 (20/10/2008)

3.1.1 Mthodologie
La complexit d'un algorithme permet d'exprimer formellement sa rapidit en fonction de la taille des donnes en entre. Pour l'valuer nement, on compte prcisment le nombre d'oprations. Attention, lors du comptage, il faut tre prudent, et ventuellement vrier sur un exemple : si une variable

passe au total par Cette notation a

valeurs direntes par l'aectation

i i + 1,

cela signie qu'il y a eu

n1

aectations au total.

terme dominant de l'expression du nombre d'oprations en fonction de la taille des donnes en entre. Si un algorithme
une dnition mathmatique base de limites, en pratique il faut retenir qu'elle correspond au eectue

Le plus souvent on se contente d'ordres de grandeurs avec la notation de Landau :

O(. . .).

5n3 + 2n

oprations pour une entre de taille

n,

le terme dominant est

n3 ,

on dit donc qu'il y a

O(n )

oprations, et que l'algorithme a une complexit cubique. Pour

O(n),

la complexit est linaire,

O(n2 ),

la complexit est quadratique, Si l'algorithme fait terme dominant est donc c'est

O( n).

O(log n), la complexit est logarithmique. n +log de grandeur de sa complexit ? Le 10 n tapes dans le pire des cas, quel est l'ordre n (pour avoir une intuition ce sujet, comparer 1000000 = 1000 log10 1000000 = 6),

3.1.2 Complexit de l'algorithme 15 (exercice 1)


Comme l'algorithme 15 contient une boucle d'itrations de cette boucle. Pour cet algorithme,

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

passe de 0

multiplications et

additions, mais

B , il y a donc B excutions de la boucle tant que, et 2+2B aectations, B + 1 comparaisons (la dernire comparaison choue et fait sortir de la

boucle). d'

exponentiation rapide 1 , qui a une complexit de O(log B ) multiplications au lieu de O(B ) pour calculer AB .

Pour approfondir : on peut proposer un algorithme plus ecace de calcul de puissance, c'est l'algorithme

Vous pouvez vous amuser en chercher un invariant pour dmontrer sa correction.

3.1.3 Complexit de l'algorithme 16' (exercice 3 complexit)


Il s'agit de compter le nombre d'itrations de chacune des boucles "pour". La premire est faite Celle l'intrieur est eectue 1 fois pour

fois.

I = 2, . . . N fois pour I = N . N N (N +1) Finalement, le nombre total d'excutions de la ligne  R R + 1; est donc i=1 i = 2
2 fois pour

I = 1,

(pour calculer,

utiliser le fait que c'est la srie d'une suite arithmtique, ou bien retrouver la formule l'aide d'un dessin). Il

N (N +1) + 1 aectations dans les lignes 1 et 2, et N (N + 1) + 1 + N = (N + 1)2 en comptant les 2 2 aectations chaches dans les boucles . La complexit en temps de l'algorithme est donc en O (N ), c'est
y a donc

Pour

dire quadratique.
1.

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

14

Donnes : A, B : entiers Rsultat : renvoie la puissance AB . Variables : p, i, x, entiers. dbut 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 11 : ExponentiationRapide(d A, B : entiers) : entier


Sance 8 (22/10/2008)

3.2

3.2.1 Arrt et complexit de l'algorithme 12 (exercice 2 complexit)


Soit Mk (resp. Zk ) la valeur de M (resp. Z ) aprs la k -ime itration de la boucle Tant que. Mk+1 Mk = Zk < 0 donc (Mk ) est une suite strictement dcroissante valeurs entires, donc elle ne peut prendre qu'un nombre ni de valeurs, et donc l'algorithme s'arrte. On pouvait aussi considrer la suite valeurs entires. Comme

uk = Mk Zk

pour obtenir une suite strictement dcroissante et

est initialis 0, incrment de 1 chaque itration de la boucle

rithme il vaut

, l'algorithme a une complexit en

O( I ).

Tant que, et qu'en n d'algo-

3.2.2 Arrt et complexit de l'algorithme 13 (exercice 2 invariants)


Soit

Ck

la valeur de

aprs la

k -ime

itration de la boucle

Tant que. Ck+1 Ck = 1 < 0 donc (Ck ) est Tant que,


et qu'en n

une suite strictement dcroissante valeurs entires, donc elle ne peut prendre qu'un nombre ni de valeurs, et donc l'algorithme s'arrte. Comme

est initialis

X,

dcrment de 1 chaque itration de la boucle

d'algorithme il vaut 0, l'algorithme a une complexit en

O (X ).

3.2.3 Arrt et complexit de l'algorithme 9 (exercice 3 arrt)


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). La valeur de n dcrot strictement chaque appel rcursif et elle est entire. Donc dans chaque branche de l'arbre (binaire) d'excution de l'algorithme, n ne peut prendre qu'un nombre ni de valeurs. Ainsi, toutes
A chaque appel de l'algorithme les branches de cet arbre binaire ont une profondeur nie donc l'arbre d'excution est ni, donc il n'y a qu'un nombre ni d'appels rcursifs, et donc l'algorithme s'arrte.

15

3.2.4 Complexit de la recherche dichotomique (exercice 3 algorithme et preuves)


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,


c'est dire qu'on veut faire un lger changement d'invariant, il sut donc de remplacer dans l'algorithme

>e

par 

e .

La complexit de cet algorithme de recherche dichotomique est logarithmique. Pour s'en convaincre, on peut reprsenter l'algorithme par un arbre de recherche : chaque appel de l'algorithme, on coupe l'intervalle de recherche en deux, puis on recherche rcursivement soit dans la partie de gauche, soit dans celle de droite. L'arbre est donc binaire (chaque tape donne naissance deux tapes possibles). Si 2, alors il a

est une puissance de

feuilles, sa profondeur est donc

log2 (n).

Or la complexit de l'algorithme, le nombre d'tapes,

correspond justement la profondeur de l'arbre, et chaque tape se fait en temps constant, la complexit en temps est donc en Si

O(log n). n
qui est la puissance de 2 juste suprieure

n'est pas une puissance de 2, on considre le nombre

(c'est dire

n =2

log2 (n) +1

), et l'arbre d'excution a donc au plus

de recherche dichotomique est en

O(log2 n ),

c'est dire en

n O(log n).

feuilles, et la complexit de l'algorithme

3.3

Sance 9 (03/11/2008)

3.3.1 Algorithme indicePrdcesseur (exercice 4 algorithme et preuve)


En pratique, pour crire ce genre d'algorithmes, on crit la structure gnrale permettant d'eectuer la recherche dichotomique, puis on vrie et on ajuste les paramtres des tests, la condition d'arrt, et les mises jour des variables. Pour ce faire, il est utile de reprsenter l'invariant qui indique la situation laquelle on veut aboutir, et d'en dduire ces dirents paramtres ajuster.

Donnes : T [1..n] : un tableau d'entiers tri par ordre croissant, x : un entier Rsultat : renvoie 0 si tous les lments de T sont suprieurs ou gaux x, sinon renvoie le plus grand Variables : Deb, F in, M il, entiers. dbut tant que Deb F in faire si T [M il] < x alors sinon n
Deb M il + 1; F in M il 1; Deb 1; F in n; M il (Deb + F in) div 2;
indice

i [1..n]

tel que

T [i] < x.

n

n renvoyer F in; Algorithme 12 : indicePred(d T [1..n] : tableau d'entiers, d x : entier) : entier


i [1..Deb[, j ]F in..n], T [i] < x T [j ].

La formule suivante, qui peut aussi tre reprsente sous forme d'un schma sur le dessin du tableau tri, est un invariant : La complexit est bien sr logarithmique.

3.3.2 Test de tri d'un tableau (exercice 4 complexit)


N 1, est atteint si T N + 1). Comme la condition d'arrt est une conjonction "A et B ", sa dernire itration, A tant valu faux, "A et B " est ncessairement faux, donc B n'est pas test. Il y a donc nalement N 1 comparaisons de type T [I ] T [I + 1] dans le pire des cas. L'algorithme a donc une complexit en O (N ).
Le nombre minimum d'itrations, 1, est atteint si

T [1] > T [2],

le nombre maximum,

est tri. Dans le pire des cas, on passe

fois par la ligne 1 (puisque

passe de 1

16

3.4

Sance 10 (05/11/2008)
Xi

3.4.1 Algorithme d'valuation d'un polynme (exercice 5 complexit)


ai . Si l'on calcule navement X i , on le fait en O (i) et la complexit de l'algorithme d'valuation du polynme en X est donc quadratique. Si on i calcule X avec l'algorithme d'exponentiation rapide prsent dans l'exercice 6 qui suit, on le fait en O (log i), soit une complexit golable O (n log n). i On peut faire mieux et atteindre une complexit linaire en stockant dans une variable R les valeurs de X i+1 calcules et en les utilisant pour calculer X .
Navement, on est tent de calculer pour tout

et de le multiplier par

Donnes : X

: un entier,

a[0..n]

: un tableau de

n+1

entiers correspondant aux coecients du

polynme.

Rsultat : renvoie la valeur R = ai X i i=0 Variables : R, P , des entiers. dbut


R 0; P 1;

du polynme en

X.

pour tous les i de 0 n faire n renvoyer R;


R R + a[i] P ; P P X;

n

Algorithme 13 : EvaluationPolynome(d X

: entier, d

a[0..n]

: tableau d'entiers) : entier

3.4.2 Algorithme de plus long prxe suxe (exercice 7 complexit)


Commenons par une version o on commence par crire le sous-problme consistant tester l'galit du prxe et du suxe d'une certaine taille.

Donnes : T [1..n] : un tableau de n entiers, k : un entier Rsultat : renvoie VRAI si le prxe et le suxe de T de longueur k sont gaux dbut pour tous les i de 1 k faire si T [i] = T [n k + i] alors renvoyer FAUX; n renvoyer VRAI; n Algorithme 14 : SuxePrexeEgaux(d T [1..n] : tableau d'entiers, d k : entier) : boolen Donnes : T [1..n] : un tableau de n entiers Rsultat : renvoie la taille du plus long prxe gal au suxe de T dbut
Variable : Variable :

i,

un entier.

et dirent de

T.

k,

un entier.

k n;

tant que k 0 et non(SuxePrexeEgaux(T, k)) faire


k k 1;

n

n renvoyer k;

Algorithme 15 : PlusLgPrefSuDecompos(d T [1..n] : tableau d'entiers) : boolen

Et maintenant une version en un seul algorithme :

17

Donnes : T [1..n] : un tableau de n entiers Rsultat : renvoie la taille du plus long prxe gal au suxe de T Variables : k, i, des entiers, et contient, un boolen. dbut
k n;

et dirent de

T.

tant que k > 0 et non(contient) faire pour tous les i de 1 k faire si T [i] = T [n k + i] alors contient Faux; n
contient

contient

Faux;

k k 1;

Vrai;

n

n renvoyer k;

Algorithme 16 : PlusLgPrefSu(d T [1..n] : tableau d'entiers) : boolen

3.4.3 Exponentiation rapide (exercice 6 complexit)


Il sut de considrer l'algorithme de multiplication russe vu en cours et de remplacer les additions par des multiplications et les initialisations 0 par des initialisations 1. Pour comprendre l'algorithme, rien de mieux que de voir son fonctionnement sur un exemple : pour

X 16 en faisant le moins de multiplications possible, l'ide est de le dcomposer en : X = (X ) = ((X 4 )2 )2 = (((X 2 )2 )2 )2 , soit simplement 4 multiplications (en commenant le calcul par 20 l'intrieur des parenthses) ! Si l'exposant n'est pas une puissance de 2, on s'adapte facilement, par exemple 2 10 2 5 2 2 2 2 2 2 se dcompose en : (X ) = ((X ) X ) = (((X ) X ) X ) , soit seulement 6 multiplications ! Dans tous les cas, si k est une puissance de 2, on a besoin de log2 k multiplications (qui sont des lvations i i+1 au carr). Sinon, si k est compris entre 2 et 2 1, on a besoin de i = log2 n lvations au carr, et au plus autant de multiplications par X . Dans tous les cas, au total, il y a (log n) oprations.
calculer rapidement

16

8 2

3.5

Sance 11 (12/11/2008)

3.5.1 Exponentiation rapide - version rcursive (exercice 6 complexit)


Donnes : A, B : deux entiers Rsultat : renvoie AB Variable : p, un entier. dbut si B = 0 alors renvoyer 1; sinon

p ExponentiationRapide(A,B si B mod 2=0 alors renvoyer p p;

div 2);

n

n

sinon renvoyer p p A; n

Algorithme 17 : ExponentiationRapide(A,B

: entiers) : entier

3.5.2 Problme SomMax (complexit)


(a) La complexit de l'algorithme propos est en (c) On peut passer

O(n3 ). i et j .

(b) Pour passer une complexit quadratique il sut de mettre jour SomMax quand on fait varier

O(n log n)

avec une approche Diviser et Rsoudre. L'ide est que le sous-tableau de

somme maximale se trouvera soit dans la premire moiti, soit dans la seconde, soit il empitera sur les deux et

18

Donnes : T [1..n] : un tableau de n entiers relatifs Rsultat : renvoie 0 si tous les lments de T sont ngatifs, la somme maximale des lments, parmi
b
tous ses sous-tableaux sinon, c'est dire

Variables : somme, un entier. dbut


SomM ax 0;

ab[1..n]

max (0,
i=a

T [i]).

pour tous les i de 1 n faire pour tous les j de i n faire n n renvoyer max(0,SomM ax);
somme 0; somme somme + T [j ]; SomM ax max(somme, SomM ax);

n

Algorithme 18 : SomMax(d T [1..n] : tableau d'entiers) : entier

a donc la somme maximale en partant du milieu dans le sous-tableau gauche, et somme maximale en partant du milieu dans le sous-tableau droit, ce qui permet de le trouver en pour un certain de

O(n).

(d) Pour obtenir un algorithme linaire, et donc optimal, considrons qu'on a les deux invariants proposs

k , et regardons ce qui se passe la case k +1. On appelle Tk le sous-tableau de somme maximale T [1..k ], et Tk le sous-tableau de somme maximale se terminant la case k de T [1..k ]. Ainsi au k -ime pas, SomM ax est la somme des lments de Tk et SomM axDroite est la somme des lments de Tk .
L'algorithme 20 peut tre raccourci pour donner l'algorithme 21 (qui semble un peu trop magique, ce qui explique la prsence de la version longue, qui est en outre plus facile modier pour renvoyer les indices de dbut et de n du tableau de somme maximale).

19

Donnes : T [1..n] : un tableau de n entiers relatifs, d, f Rsultat : renvoie 0 si tous les lments de T
sous-tableau considr tous ses sous-tableaux sinon, c'est dire

: deux entiers, les indices de dbut et n du

sont ngatifs, la somme maximale des lments, parmi

b ab[1..n]

max (0,
i=a

T [i]).

Variables : sommeGauche, sommeDroite : deux entiers. dbut si d=f alors renvoyer max(0, T [d]) sinon

sommeGauche 0; somme 0; f pour tous les i de d+ d par pas de -1 faire 2 somme somme + T [i]; sommeGauche max(somme, sommeGauche);

n

sommeDroite 0; somme 0; f pour tous les i de d+ + 1 f faire 2 somme somme + T [i]; sommeDroite max(somme, sommeDroite);

n renvoyer
max

0, sommeGauche + sommeDroite, RecSomMax(T, d,

n n Algorithme 19 : RecSomMax(d T [1..n] : tableau d'entiers, d d : entier, d f

d+f 2

), RecSomMax(T,

d+f 2

+ 1, f )

: entier): entier

20

Donnes : T [1..n] : un tableau de n entiers relatifs, d, f Rsultat : renvoie 0 si tous les lments de T
sous-tableau considr tous ses sous-tableaux sinon, c'est dire

: deux entiers, les indices de dbut et n du

sont ngatifs, la somme maximale des lments, parmi

b ab[1..n]

max (0,
i=a

T [i]).

Variables : SomM ax, SomM axDroite : deux entiers. dbut

SomM ax T [1]; SomM axDroite T [1]; pour tous les k de 2 n faire si SomM axDroite 0 alors si SomM axDroite + T [k] > SomM ax alors //Le nouveau tableau optimal Tk est Tk1 + SomM ax SomM axDroite + T [k ]; SomM axDroite SomM axDroite + T [k ];

la

k -ime

case :

sinon

n sinon

SomM axDroite SomM axDroite + T [k ];

//SomM axDroite

si T [k] > SomM ax alors


//Le nouveau tableau optimal

<0

Tk

est uniquement la

k -ime

case :

sinon n

SomM ax T [k ]; SomM axDroite T [k ]; SomM axDroite T [k ];

n Algorithme 20 : SomMax4Long(d T [1..n] : tableau d'entiers, d d : entier, d f

n n renvoyer max(SomM ax,0);

: entier): entier

Donnes : T [1..n] : un tableau de n entiers relatifs, d, f Rsultat : renvoie 0 si tous les lments de T
sous-tableau considr tous ses sous-tableaux sinon, c'est dire

: deux entiers, les indices de dbut et n du

sont ngatifs, la somme maximale des lments, parmi

b ab[1..n]

max (0,
i=a

T [i]).

Variables : SomM ax, SomM axDroite : deux entiers. dbut

n Algorithme 21 : SomMax4Court(d T [1..n] : tableau d'entiers, d d : entier, d f

n renvoyer max(SomM ax,0);

SomM ax T [1]; SomM axDroite T [1]; pour tous les k de 2 n faire SomM axDroite max(SomM axDroite + T [k ], T [k ]); SomM ax max(SomM axDroite, SomM ax);

: entier): entier

21

Chapitre 4
Listes chanes

4.1

Sance 12 (17/11/2008)

4.1.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 22

(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 22 : 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. Dans le cas o vous choisissez

cette dernire solution, assurez-vous que

n'est pas vide.

4.1.2 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, 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.

4.1.3 Adresse de la dernire cellule d'une liste


L'algorithme 23 a une complexit linaire puisqu'on doit parcourir toute la liste pour atteindre sa dernire cellule (alors qu'avec une liste doublement chane on peut accder l'adresse de la dernire cellule de la liste en temps constant).

22

Figure

4.1 

Utilisation des listes chanes : aprs la ligne 1 (a), 2 (b), 3 (c), 4 (d), 5 (e),

rorganisation (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).

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

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

4.2

Sance 13 (19/11/2008)

4.2.1 Premier lment mis la n d'une liste


L'algorithme 24 est aussi linaire (on peut l'crire en temps constant avec une liste doublement chane). Notons qu'on s'arrte juste avant d'tre arriv la n de la liste, c'est dire qu'on quitte la boucle ds qu'on atteint le dernier lment, pour viter de perdre l'adresse de la dernire cellule.

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


L'algorithme Supprimer vu en cours a une complexit en complexit en

O(n), donc SupprimeValeur (algorithme 25) a une

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 SupprimeValeurD (algorithme 26), en utilisant une liste doublement chane, est linaire. En fait, on peut aussi arriver cette complexit avec une liste simplement chane, en retenant l'adresse de la case prcdente dans une mmoire, ou bien en procdant de manire dcale, et en testant si la contient

case suivante

e,

et non la case courante, comme dans l'algorithme 27.

23

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 Q;


QQ
succ;

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

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 24 : PremierALaFin(L : liste simplement chane) : liste simplement chane

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 = NULL faire si Q info = e alors n n n


Supprimer(L,Q); succ;

alors renvoyer NULL;

QQ

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

24

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

Q,

liste doublement chane.

renvoyer NULL; n tant que Q = L faire si Q info = e alors


//Le prdcesseur de la case courante pointe vers son successeur :

Q L succ; si Q = NULL alors

pred succ

succ pred

Q Q

succ ; pred ;

//Le successeur de la case courante pointe vers son prdcesseur :

n n n

QQ

succ;

Algorithme 26 : SupprimeValeurD(L : liste doublement chane, e : entier)

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 succ info = e alors sinon n n


Q
succ

alors renvoyer NULL;

Q
succ;

succ

succ;

QQ

n

Algorithme 27 : SupprimeValeurB(L : liste simplement chane, e : entier)

25

4.3

Sance 14 (26/11/2008)

4.3.1 Suppression de doublons conscutifs d'une liste


Comme dans l'exercice prcdent, il faut tre un peu habile pour crire l'algorithme 28 : si, en dtectant un doublon dans la case suivante, on veut supprimer la case actuelle, alors il faut retenir l'adresse de la case prcdente pour la relier la suivante. Au lieu de a, il vaut mieux supprimer la case suivante, en reliant l'actuelle celle qui suivra.

Donnes : L : liste simplement chane non vide Rsultat : supprime de L tous les doublons conscutifs dbut
Variable :

Q,

liste simplement chane.

Q L;

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

Q
succ;

succ

succ;

QQ

n

Algorithme 28 : SupprimeDoublonsConsecutifs(L : liste simplement chane non vide)

4.3.2 Concatnation de deux listes simplement chanes


L'algorithme 29 de concatnation de deux listes case de

L1

et

L2

en temps linaire consiste atteindre la dernire

L1

pour la lier la premire de

L2 .

Donnes : L1 , L2 : listes simplement chanes Rsultat : modie L1 pour lui concatner L2 dbut
Variable :

Q,

liste simplement chane.

n tant que Q succ = NULL faire n n


QQ
succ succ;

Q L1 ; si Q = NULL L1 L2 ;

alors

L1

L2

Algorithme 29 : Concatene(L1 , L2

: listes simplement chanes)

4.3.3 Concatnation de deux listes doublement chanes


Rappel sur la structure des listes doublement chane :
Une liste doublement chane est constitue de cases qui contiennent une valeur et qui pointent vers la case suivante ou vers la case prcdente. Elle contient aussi une sorte de table des matires qui pointe vers la premire et vers la dernire case, et vers qui pointent la premire et la dernire case (voir dessin dans le cours). Ainsi, la premire valeur de la liste doublement chane

est

succ

info, sa dernire valeur est

pred

info. L'intrt est donc de pouvoir accder la case prcdente, ou bien la dernire case, en temps constant. En utilisant des listes doublement chanes, on peut donc eectuer la concatnation en temps constant, avec l'algorithme 30. Il faut juste tre soigneux pour assurer que les bonnes ches pointent au bon endroit. De plus, contrairement la version avec les listes simplement chanes o en version doublement chane, plus vers la table des matires

L2 restait une liste valide aprs concatnation, L2 sera dtruite dans l'opration puisque la dernire case de L2 ne pointera de L2 , mais vers celle de L1 .
26

Donnes : L1 , L2 : listes doublement chanes Rsultat : modie L1 pour lui concatner L2 dbut
// La dernire case de pred

n

L1 pointe vers la premire de L2 : L2 succ; // La premire case de L2 pointe vers la dernire de L1 : L2 succ pred L1 pred; // La dernire case de L2 pointe vers la table des matires L2 pred succ L1 ; // La table des matires de L1 pointe vers la dernire case L1 pred L2 pred; L1
succ

de de

L1 L2

: :

Algorithme 30 : ConcateneDC(L1 , L2 : listes doublement chanes)

27

Chapitre 5
Arbres

5.1

Fin de la sance 14 (26/11/2008)

5.1.1 Familiarisation avec les arbres


valeur la

A trois cases qui reprsente la racine de l'arbre, contient une A info, et un pointeur vers la cellule-racine de son sous-arbre gauche A sag, ainsi qu'un pointeur vers cellule-racine de son sous-arbre droit A sad. Les nuds au bout des branches (nuds de degr 1) d'un
Un arbre binaire est cod comme une cellule Pour parcourir une liste, on pouvait partir de la tte et suivre les pointeurs vers les successeurs jusqu'

arbre binaire sont appels feuilles, ils pointent vers NULL gauche et NULL droite. arriver la n de la liste et donc un pointeur vers NULL l'aide d'une boucle une boucle

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 permet de rsoudre le problme sur 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))

5.2

Sance 15 (03/12/2008)

5.2.1 Hauteur d'un arbre binaire


Ide de l'algorithme 31
: 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 31 : Hauteur(A : arbre binaire) : entier

5.2.2 Nombre de feuilles d'un arbre binaire


Ide de l'algorithme 32
: 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.

28

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 32 : NombreFeuilles(A : arbre binaire) : entier

5.2.3 Eeuillage d'un arbre binaire


Ide de l'algorithme 33 : l'eeuillage consiste eeuiller rcursivement le sous-arbre gauche et le sousarbre droit de la racine de l'arbre.

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 33 : Eeuillage(A : arbre binaire) : entier

29

Chapitre 6
Tris

On notera dans la suite

|T |

la taille d'un tableau

pour plus de simplicit.

6.1

Sance 16 (10/12/2008)

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


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

A et B , on va mettre dans une liste tout lment

et

B.

Sans doublons
Dans un premier temps on considrera qu'il n'y a pas de doublons, puis on ajoutera une procdure pour les prendre en compte qui ne changera rien l'ordre de grandeur de la complexit des algorithmes. prsent parmi les

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

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

O(|A||B |).

Donnes : A, B : tableaux d'entiers sans doublons, B est tri. Rsultat : Renvoie le nombre d'entiers prsents dans les deux tableaux.
Variables :

dbut

t,

entier.

t 0; pour i de 1 |A| faire pour j de 1 |B | faire si A[i] = B [j ] alors t t + 1;

n

n renvoyer t; Algorithme 34 : TailleIntersectionNaif(A, B


O(log |B |) s'il est prsent O(|A| log |B |).
: tableaux) : entier

n

n

Ide de l'algorithme 35 avec un des deux tableaux tri : pour chacun des |A| lments du premier
tableau, on regarde par dichotomie en parmi les lments du second tableau qui sont tris. On obtient donc une complexit en en Si le tableau B n'est pas tri, on peut commencer par le trier en O (|B | log |B |). La complexit totale est donc O(|A| log |B | + |B | log |B |), c'est dire O(max(|A|, |B |) log |B |), elle est meilleure qu'avec l'ide prcdente.

Ide de l'algorithme 36 avec les deux tableaux tris : on parcourt simultanment les deux tableaux
O(|A| + |B |).

pour obtenir une complexit en

Si on considre que les deux tableaux ne sont pas tris, on commence par trier le premier tableau en

O(|A| log |A|), puis le second en O(|B | log |B |), ce qui donne une complexit totale en O(|B | log |B | + |A| log |A| + |A| + |B |), soit O(max(|A|, |B |) log max(|A|, |B |)), ce qui est encore meilleur que l'ide prcdente.

30

Donnes : A, B : tableaux d'entiers sans doublons, B est tri. Rsultat : Renvoie le nombre d'entiers prsents dans les deux tableaux.
Variables :

dbut

t,

entier.

t 0; pour i de 1 |A|

faire si RechercheDicho(B ,A[i]) alors n


t t + 1;

n

n renvoyer t; Algorithme 35 : TailleIntersection1Tri(A, B


: tableaux) : entier

Donnes : A, B : tableaux d'entiers sans doublons, A et B sont tris. Rsultat : Renvoie le nombre d'entiers prsents dans les deux tableaux.
Variables :

dbut

t,

entier.

t 1; i 1; j 0; tant que i + j |A| + |B | si A[i] < B [j ] alors i i + 1;

faire

sinon si B [j ] < A[i] alors sinon


j j + 1;

n

n renvoyer t; Algorithme 36 : TailleIntersection2Tris(A, B


: tableaux) : entier

n

n

i i + 1; j j + 1; t t + 1;

31

Avec doublons
Pour les deux premiers algorithmes, l'ide est de garder en mmoire dans une variable deux tableaux dj trouve. A chaque fois qu'un lment est trouv la fois dans le tableau

B,

on vrie s'il est dj dans

puisque

X . Si non, on l'y ajoute. Cette opration est donc faite |A B | min(|A|, |B |). Quelle structure de donnes utiliser pour X ? Il faut en choisir une qui permet O(log n), O(n) O(log n) recherche en O (nauteur), insertion
insertion en

X l'intersection des A et dans le tableau O(min(|A|, |B |)) fois

des oprations de recherche et d'insertion rapide :  tableau tri : recherche en  tas : recherche en

O(n),

insertion en

 arbre binaire de recherche :

en

O(nauteur)

(o hauteur est logarith-

mique en moyenne, mais possiblement linaire).  pour avoir des oprations de recherche et d'insertion logarithmique, et donc garder le mme ordre de grandeur de la complexit en

O(|A| log |B |)

plus perfectionne : arbre AVL

1 ou arbre rouge noir 2 . . .

pour l'algorithme 35, il faut utiliser une structure de donnes

Pour le troisime algorithme, c'est plus simple : il sut de poursuivre l'incrmentation des compteurs tant que des lments identiques sont dcouverts, c'est dire insrer juste aprs la ligne

A[i] = A[i 1]

faire i i + 1, puis : tant que B [j ] = B [j 1] faire j j + 1.

t t + 1;

tant que

et

6.1.2 Test de l'existence de doublons


Un algorithme naf pour vrier si les lment s'il est prsent dans une des faire mieux en commenant par

n lments d'un tableau sont dirents est de tester pour chaque n 1 autres cases. Cet algorithme a une complexit quadratique. On peut trier le tableau en O (n log n) ce qui aura pour eet de rapprocher les doublons

si le tableau en contient. Il sut alors d'utiliser l'algorithme 37 qui parcourt en temps linaire un tableau tri pour vrier qu'il ne contient pas de doublon.

Donnes : T : tableau contenant n entiers tris. Rsultat : Renvoie VRAI si le tableau ne contient que des lments dirents, FAUX sinon
Variables :

dbut

i,

entier.

i 1;

tant que i < n et T [i] = T [i + 1] faire n n renvoyer (i = n); Algorithme 37 : TousDierents(T


: tableau) : boolen

i i + 1;

6.2

Sance 17 (17/12/2008)

6.2.1 Tri par fusion


Voir les algorithmes 38 et 39. Dans le pire comme dans le meilleur cas, l'algorithme a une complexit en

O(n log n).

6.2.2 Tri de notes


L'algorithme 40 a une complexit linaire en la taille du tableau. Si on le gnralise pour trier un tableau d'entiers compris entre 0 et

k, k

tant fourni en paramtre, il a une complexit en

O(k + n).

6.2.3 Tri par base


T [j ][l] dsigne le lme chire du j me nombre de T , il s'agit du lme de poids faible. Par exemple, si T = [139, 1042, 225], T [3][1] = 5 et T [3][4] = 0. L'algorithme 41 a une complexit en O (kn).
Dans l'nonc, quand il est dit que
1. 2.

chire

http://fr.wikipedia.org/wiki/Arbre_AVL http://fr.wikipedia.org/wiki/Arbre_rouge-noir
32

Donnes : T [1..n] : tableau. Rsultat : Renvoie un tableau tri contenant les lments de T dbut si n > 1 alors renvoyer Fusion(T riF usion(T [1.. n/2 ], T [ n/2 + 1..n])); sinon renvoyer T ; n n Algorithme 38 : TriFusion(T : tableau) : tableau

Donnes : T 1, T 2 : tableaux tris. Rsultat : Renvoie un tableau tri contenant les lments de T 1 et T 2
Variables :

dbut

T,

tableau d'entiers

T T [1..|T 1| + |T 2|]; i 1; j 1; tant que i + j |T 1| + |T 2| si i > |T 1| alors T [i + j 1] T 2[j ];

faire

sinon si j > |T 2| alors

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

T [i + j 1] T 1[i];

T [i + j 1] T 1[i]; i i + 1; T [i + j 1] T 2[j ]; j j + 1;

n

n n renvoyer T ; Algorithme 39 : Fusion(T 1, T 2 : tableaux tris) : tableau

33

Donnes : T : tableau d'entiers compris entre 0 et 20. Rsultat : Renvoie un tableau tri contenant les lments de T dbut n n
Variables :

N bN otes[1..21], N bN otes

tableau

//Cration de

pour i de 1 21 faire
N bN otes[i] 0;
//Remplissage de

pour i de 1 |T | faire
//Dveloppement de

N bN otes

N bN otes[T [i] + 1] N bN otes[T [i] + 1] + 1;

n

n n renvoyer T ;

N bN otes j 1; pour i de 1 |N bN otes| faire k 0; tant que k < N bN otes[i] faire T [j ] i 1; j j + 1; k k + 1;

Algorithme 40 : TriNotes(T

: tableau d'entiers compris entre 0 et 20) : tableau

Donnes : T [1..n] : tableau d'entiers ayant au plus k chires. Rsultat : Renvoie un tableau tri contenant les lments de T
Variables :

dbut n n

F [0..9], k
:

tableau

//Calcul de

pour i de 1 |T | faire pour i de 0 9 faire


F [i] crerFile();
//Tri du tableau :

k max(k, log10 T [i] );

//Initialisation du tableau de les :

pour i de 1 k + 1 faire
//Remplissage du tableau de les tri selon le

pour j de 1 |T | faire n
//Remplissage de

ime

chire :

ajouterFile(F [T [j ][i]], T [j ])

a1

pour j de 0 9 faire tant que non(FileVide?(F [j ])) faire


T [a]
tteFile(F [j ]); retirerFile(F [j ]);

T,

tri selon les

chires de poids faible :

n

n renvoyer T ; Algorithme 41 : TriBase(T


: tableau de

n

n

a a + 1;

entiers) : tableau

34