Vous êtes sur la page 1sur 124

Analyse des algorithmes:

une introduction
La question aborde dans ce chapitre est la
suivante:

Comment choisir parmi les diffrentes
approches pour rsoudre un problme?



Exemples: Liste chane ou tableau?
algorithme de tri par insertion de tri
rapide?
, etc
Pour comparer des solutions,
plusieurs points peuvent tre pris en
considration
Exactitude des programmes (dmontrer que le
rsultat de limplantation est celui escompt)
Simplicit des programmes
Convergence et stabilit des programmes (il est
souhaitable que nos solutions convergent vers la
solution exacte; la perturbation des donnes ne
chamboule pas dune manire drastique la solution
obtenue)
Efficacit des programmes (il est souhaitable que
nos solutions ne soient pas lentes, ne prennent pas
de lespace mmoire considrable)
Le point que nous allons dvelopper dans
ce chapitre est celui de lefficacit des
algorithmes.
Dfinition: Un algorithme est un ensemble
dinstructions permettant de transformer un
ensemble de donnes en un ensemble de
rsultats et ce, en un nombre fini tapes.

Pour atteindre cet objectif, un algorithme
utilise deux ressources dune machine: le
temps et lespace mmoire.
Dfinition 1: la complexit temporelle dun
algorithme est le temps mis par ce dernier
pour transformer les donnes du problme
considr en un ensemble de rsultats.

Dfinition 2: la complexit spatiale dun
algorithme est lespace utilis par ce dernier
pour transformer les donnes du problme
considr en un ensemble de rsultats.

Comparaison de solutions
Pour comparer des solutions entre-elles, deux
mthodes peuvent tre utilises:

Mthode empirique
Mthode mathmatique


Cette comparaison se fera, en ce qui nous
concerne, relativement deux ressources
critiques: temps, espace mmoire,...

Dans ce qui suit, nous allons nous concentrer
beaucoup plus sur le temps dexcution

Facteurs affectant le temps dexcution:

1. machine,
2. langage,
3. programmeur,
4. compilateur,
5. algorithme et structure de donnes.

Le temps dexcution dpend de la longueur de
lentre.

Ce temps est une fonction T(n) o n est la
longueur des donnes dentre.


Exemple 1: x=3; la longueur des donnes
dans ce cas est limite une seule
variable.

Exemple 3:

sum = 0;
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
sum++;

En revanche, dans ce cas, elle est fonction
du paramtre n
}
La longueur des donnes dentre,
dfinissant le problme considr, est
dfinie comme tant lespace quelle occupe
en mmoire.
Cet espace est logarithmique de la valeur
considre. Par exemple, le nombre N
occupe log N bits despace mmoire.


Pire cas, meilleur cas et cas moyen
Toutes les entres dune taille donne ne ncessitent
pas ncessairement le mme temps dexcution.

Exemple:

soit rechercher un lment C dans un tableau de n
lment tris dans un ordre croissant.

Deux solutions soffrent nous:

1. Recherche squentielle dans un tableau de taille n.
Commencer au dbut du tableau et considrer
chaque lment jusqu ce que llment cherch
soit trouv soit declar inexistant.

2. Recherche dichotomique: tient compte du
fait que les lments du tableau soient dj
tris. Information ignore par lalgorithme
de la recherche squentielle.

Ces deux algorithmes sont prsents comme
suit:
int recherche(int *tab, int C){
int i;
i = 0;
while (i<n && tab[i] != C )
i = i+1;
if (i == n)
return(0);
else return(i);
} /* fin de la fonction */
int recherche(int *tab, int C){
int sup, inf, milieu;
bool trouve;
inf = 0; sup = n-1; trouve = false;
while (sup >=inf && !trouve) {
milieu = (inf + sup) / 2;
if (C == tab[milieu])
trouve = true;
else if (C < tab[milieu])
sup = milieu -1;
else inf = milieu + 1;
if (!trouve)
return(0);
return(milieu)
} /* fin de la fonction */

La mthode empirique
Elle consiste coder et excuter deux (ou
plus) algorithmes sur une batterie de
donnes gnres dune manire alatoire
chaque excution, le temps dexcution
de chacun des algorithmes est mesur.
Ensuite, une tude statistique est entreprise
pour choisir le meilleur dentre-eux la
lumire des rsultats obtenus.
Problme!
Ces rsultats dpendent

la machine utilise;
jeu dinstructions utilises
lhabilet du programmeur
jeu de donnes gnres
compilateur choisi
lenvironnement dans lequel est excut les
deux algorithmes (partags ou non)
.... etc.

Mthode mathmatique
Pour pallier ces problmes, une notion de
complexit plus simple mais efficace a t
propose par les informaticiens.
Ainsi, pour mesurer cette complexit, la
mthode mathmatique consiste non pas
la mesurer en secondes, mais faire le
dcompte des instructions de base excutes
par ces deux algorithmes.

Cette manire de procder est justifie
par le fait que la complexit dun
algorithme est en grande partie induite
par lexcution des instructions qui le
composent.
Cependant, pour avoir une ide plus
prcise de la performance dun
algorithme, il convient de signaler que
la mthode exprimentale et
mathmatique sont en fait
complmentaires.
Comment choisir entre plusieurs
solutions?
1. dcompte des instructions
Reconsidrons la solution 1 (recherche
squentielle) et faisons le dcompte des
instructions. Limitons-nous aux instructions
suivantes:

Affectation note par e
Test not par t
Addition note par a


Il est clair que ce dcompte dpend non seulement
de la valeur C mais de celles des lments du
tableau.

Par consquent, il y a lieu de distinguer trois
mesures de complexit:

1. dans le meilleur cas
2. dans le pire cas
3. dans la cas moyen
Meilleur cas: note par tmin(n) reprsentant la complexit
de lalgorithme dans le meilleur des cas en fonction du
paramtre n (ici le nombre dlments dans le tableau).

Pire cas: note par tmax(n) reprsentant la complexit de
lalgorithme dans le cas le plus dfavorable en fonction du
paramtre n (ici le nombre dlments dans le tableau).

Cas Moyen: note par tmoy(n) reprsentant la complexit
de lalgorithme dans le cas moyen en fonction du
paramtre n (ici le nombre dlments dans le tableau).
Cest--dire la moyenne de toutes les complexits, t(i),
pouvant apparatre pour tout ensemble de donnes de taille
n (t(i) reprsente donc la complexit de lalgorithme dans
le cas o C se trouve en position i du tableau). Dans le cas
o lon connat la probabilit Pi de ralisation de la valeur
t(i), alors par dfinition, on a:


) ( ... ) 1 ( ) (
1
n t p t p n t
n moy
+ + =
Il est clair que pour certains algorithmes, il
ny a pas lieu de distinguer entre ces trois
mesures de complexit. Cela na pas
vraiment de sens.
Meilleur cas pour la recherche squentielle:
Le cas favorable se prsente quand la valeur
C se trouve au dbut du tableau

tmin(n) = e + 3t (une seule affectation et 3
test: deux dans la boucle et un autre
lextrieur de la boucle)

Pire cas: Le cas dfavorable se prsente
quand la valeur C ne se trouve pas du tout
dans le tableau. Dans ce cas, lalgorithme
aura examiner, en vain, tous les lments.

tmax(n) = 1e + n(2t+1e+ 1a)+ 1t + 1t
= (n+1)e + na + (2n+2)t
Cas moyen: Comme les complexits favorable et dfavorable
sont respectivement (e + 3t) et (n+1)e + na + (2n+3)t, la
complexit dans le cas moyen va se situer entre ces deux
valeurs. Son calcul se fait comme suit:

On suppose que la probabilit de prsence de C dans le
tableau A est de . De plus, dans le cas o cet lment C
existe dans le tableau, on suppose que sa probabilit de
prsence dans lune des positions de ce tableau est de 1/n.

Si C est dans la position i du tableau, la complexit t(i) de
lalgorithme est:

t(i) = (i+1)e + ia + (2i+2)t





Par consquent, dans le cas o C existe, la complexit
moyenne de notre algorithme est :










t n a n e n n X
t i ia e i
n
n X
moy
n
i
moy
) 4 ( ) 1 (
2
1
) 1 3 (
2
1
) (
) 2 2 ( ) 1 (
1
) (
0
+ + + + + =
+ + + + =

=
Par analogie, si llment C nexiste pas
dans le tableau, la complexit de notre
algorithme est tmax(n).
Par consquent:






t n a n e n n T
n T n X
n
n T
moy
moy moy
) 7 3 (
2
1
) 1 3 (
2
1
) 1 (
4
5
) (
) ( ) ( (
1
) (
max
+ + + + + =
+ =
Complexit asymptotique
Le dcompte dinstructions peut savrer
fastidieux effectuer si on tient compte dautres
instructions telles que: accs un tableau, E/S,
oprations logiques, appels de fonctions,.. etc.
De plus, mme en se limitant une seule
opration, dans certains cas, ce dcompte peut
engendrer des expressions que seule une
approximation peut conduire une solution.
Par ailleurs, mme si les oprations lmentaires
ont des temps dexcution constants sur une
machine donne, ils sont diffrents dune machine
une autre.

Par consquent:
Pour ne retenir que les caractristiques essentielles
dune complexit, et rendre ainsi son calcul simple
(mais indicatif!), il est lgitime dignorer toute
constante pouvant apparatre lors du dcompte du
nombre de fois quune instruction est excute.

Le rsultat obtenu laide de ces simplifications
reprsente la complexit asymptotique de
lalgorithme considr.
Ainsi, si
tmax(n) = (n+1)e + (n-1)a + (2n+1)t,
alors on dira que la complexit de cet algorithme est
tout simplement en n. On a limin tout
constante, et on a suppos aussi que les oprations
daffectation, de test et daddition ont des temps
constants.

Dfinition: La complexit asymptotique dun
algorithme dcrit le comportement de celui-ci
quand la taille n des donnes du problme trait
devient de plus en plus grande, plutt quune
mesure exacte du temps dexcution.
Une notation mathmatique, permettant de
reprsenter cette faon de procder, est
dcrite dans ce qui suit:
Notation grand-O
La notation grand-O indique une borne
suprieure sur le temps dexcution.

Exemple: Si T(n) = 3n
2
+2
alors T(n) O(n
2
).

On dsire le plus de prcision possible:
Bien que T(n) = 3n
2
+2 O(n
3
),
on prfre O(n
2
).
Dfinition: Soit T(n) une fonction non
ngative. T(n) est en O(f(n)) sil existe
deux constante positives c et n
0
telles
que:
T(n) <= cf(n) pour tout n >= n
0
.


Utilit: Le temps dexcution est born

Signification: Pour toutes les grandes entres (i.e.,
n >= n
0
), on est assur que lalgorithme ne
prend pas plus de cf(n) tapes.
Borne suprieure.
Grand-O: Exemples
Exemple 1: Initialiser un tableau dentiers
for (int i=0; i<n; i++) Tab[i]=0;
Il y a n itrations
Chaque itration ncessite un temps <= c,
o c est une constante (accs au tableau + une
affectation).
Le temps est donc T(n) <= cn
Donc T(n) = O(n)
Grand-O: Exemples
Exemple 2: T(n) = c
1
n
2
+ c
2
n .
c
1
n
2
+ c
2
n <= c
1
n
2
+ c
2
n
2
= (c
1
+ c
2
)n
2

pour tout n >= 1.

T(n) <= cn
2
o c = c
1
+ c
2
et n
0
= 1.

Donc, T(n) est en O(n
2
).

Exemple 3: T(n) = c. On crit T(n) = O(1).
Grand-Omega
Dfinition: Soit T(N), une fonction non
ngative. On a T(n) = O(g(n)) sil existe
deux constantes positives c et n
0
telles
que T(n) >= cg(n) pour n > n
0
.

Signification: Pour de grandes entres,
lexcution de lalgorithme ncessite au
moins cg(n) tapes.

Borne infrieure.
Grand-Omega: Exemple
T(n) = c
1
n
2
+ c
2
n.

c
1
n
2
+ c
2
n >= c
1
n
2
pour tout n > 1.
T(n) >= cn
2
pour c = c
1
et n
0
= 1.

Ainsi, T(n) est en O(n
2
) par dfinition.

Noter quon veut la plus grande borne infrieure.
La notation Theta
Lorsque le grand-O et le grand-omega
dune fonction concident, on utilise alors
la notation grand-theta.

Dfinition: Le temps dexcution dun
algorithme est dans O(h(n)) sil est la
fois en O(h(n)) et O(h(n)).
Exemple
O(n)
O(n
2
)
O(n
3
)
O(2
n
)
O(lg n)
O(lg n) = O(n) = O(n
2
) = O(n
3
) = O(2
n
)
Taux de croissance
Remarques
Le meilleur cas pour mon algorithme est
n = 1 car cest le plus rapide. FAUX!

On utilise la notation grand-O parce quon
sintresse au comportement de lalgorithme
lorsque n augmente et non dans le pire cas.

Meilleur cas: on considre toutes les entres de
longueur n.
Notes
Ne pas confondre le pire cas avec la
notation asymptotique.

La borne suprieure rfre au taux de
croissance.

Le pire cas rfre lentre produisant le
plus long temps dexcution parmi toutes
les entres dune longueur donne.
Rgles de simplification 1
Si
f(n) = O(g(n))
et
g(n) = O(h(n)),

alors
f(n) = O(h(n)).

Rgles de simplification 2

Si
f(n) = O(kg(n))
o k > 0 est une constante,

alors
f(n) = O(g(n)).


Rgles de simplification 3

Si
f
1
(n) = O(g
1
(n))
et
f
2
(n) = O(g
2
(n)),

alors
(f
1
+ f
2
)(n) = O(max(g
1
(n), g
2
(n)))
Rgles de simplification 4

Si
f
1
(n) = O(g
1
(n))
et
f
2
(n) = O(g
2
(n))

alors
f
1
(n)f
2
(n) = O(g
1
(n) g
2
(n))
Quelques rgles pour calculer la
complexit dun algorithme
Rgle 1: la complexit dun semble
dinstructions est la somme des complexits
de chacune delles.
Rgle 2: Les oprations lmentaires telle
que laffectation, test, accs un tableau,
oprations logiques et arithmtiques, lecture
ou criture dune variable simple ... etc, sont
en O(1) (ou en O(1))
Rgle 3: Instruction if: maximum entre
le then et le else

switch: maximum parmi les diffrents
cas

Rgle 4: Instructions de rptition

1. la complexit de la boucle for est calcule par la
complexit du corps de cette boucle multiplie par
le nombre de fois quelle est rpte.

2. En rgle gnrale, pour dterminer la complexit
dune boucle while, il faudra avant tout dterminer
le nombre de fois que cette boucle est rpte,
ensuite le multiplier par la complexit du corps de
cette boucle.

Rgle 5: Procdure et fonction: leur complexit est
dtermine par celui de leur corps. Lappel une
fonction est suppos prendre un temps constant en
O(1) (ou en O(1))

Notons quon fait la distinction entre les fonctions
rcursive et celles qui ne le sont pas:

Dans le cas de la rcursivit, le temps de calcul est
exprim comme une relation de rcurrence.
Exemples
Exemple 1: a = b;

Temps constant: O(1).

Exemple 2:

somme = 0;
for (i=1; i<=n; i++)
somme += n;

Temps: O(n)
Exemple 3:

somme = 0;
for (j=1; j<=n; j++)
for (i=1; i<=n; i++)
somme++;
for (k=0; k<n; k++)
A[k] = k;


Temps: O(1) + O(n
2
) + O(n) = O(n
2
)
Exemple 4:

somme = 0;
for (i=1; i<=n; i++)
for (j=1; j<=i; j++)
somme++;


Temps: O(1) + O(n
2
) = O(n
2
)

On peut montrer : O(n
2
)
Exemple 5:

somme = 0;
for (k=1; k<=n; k*=2)
for (j=1; j<=n; j++)
somme++;


Temps: O(nlog n) pourquoi?
Efficacit des algorithmes
Dfinition: Un algorithme est dit efficace si sa
complexit (temporelle) asymptotique est dans
O(P(n)) o P(n) est un polynme et n la taille des
donnes du problme considr.
Dfinition: On dit quun algorithme A est
meilleur quun algorithme B si et seulement si:




O et sont les complexits des
algorithmes A et B, respectivement.
et n t O n t
B A
); ( ( ) ( =
)) ( ( ) ( n t O n t
A B
=
) (n t
A
) (n t
B
Meilleur algorithme ou ordinateur?
On suppose que lordinateur utilis peut effectuer 10
6
oprations la
seconde
Robustesse de la notation O, O
et O
Z6 = T6 +
log 100/ logT6 1
T6 n! A6
Z5 = T5+log 100
T5
2
n
A5
Z4 = 10T4
T4
n
2
A4
Z3 =100T3
T3 n log n A3
Z2 =100T2
T2 n A2
Z1= (T1)
100
T1 log n A1
Taille max.
Rsolue par les
machines 100 fois
plus rapides
Taille max.
Rsolue par les
machines
actuelles
Complexit Algorithmes
Remarque
Les relations entre les complexits Ti et Zi,
donnes dans le tableau prcdent, peuvent
tre obtenues en rsolvant lquation
suivante:

100 f(Ti) = f(Zi)
O f(.) reprsente la complexit de
lalgorithme considr.
Exemple.
Pour lalgorithme A6 (n!), nous avons
rsoudre lquation suivante:
100 (T6)! = (Z6)!
Pour les grandes valeurs de n, nous avons la
formule suivante (de Stirling)

n
e
n
n
|
.
|

\
|
= !
Par consquent, on obtient ce qui suit:




En introduisant la fonction log, on obtient:



En posant Z6 = T6 + c, en approximant log (T6+ c)
par log T6, pour de trs petites valeurs de c, on
obtient:




6 6
6 6
100
Z T
e
Z
e
T
|
.
|

\
|
=
|
.
|

\
|
( ) ( ) 1 6 log 6 1 6 log 6 100 log = + Z Z T T
1 6 log
100 log
6 6

+ =
T
T Z
Exemples danalyse dalgorithmes
non rcursifs


Exemple1. Produit de deux matrices

void multiplier(int *A[][p], int *B[][m], int *C[][m],
int n, int m, int p){
for (i = 0; i<n; i++)
for (j=0; j<m; j++){
S = 0;
for(k =0; k<p; k++)
S = S + A[i][k]*B[k][j];
C[i][j] = S;
} /* fin de la boucle sur j */
} /* fin de la fonction */


Analyse: le corps de la boucle sur k est en
O(1) car ne contenant quun nombre
constant doprations lmentaires. Comme
cette boucle est itre p fois, sa complexit
est alors en O(p). La boucle sur j est itre
m fois. Sa complexit est donc en m.O(p) =
O(mp). La boucle sur i est rpte n fois.
Par consquent, la complexit de tout
lalgorithme est en O(nmp).

Note: Il est clair quil ny pas lieu de
distinguer les diffrentes complexits: dans
tous les cas, nous aurons effectuer ce
nombre doprations.
2. Impression des chiffres
composant un nombre

Le problme consiste dterminer les chiffres
composant un nombre donn. Par exemple, le
nombre 123 est compos des chiffres 1, 2 et 3.
Pour les trouver, on procde par des divisions
successives par 10. A chaque fois, le reste de la
division gnre un chiffre. Ce processus est rpt
tant que le quotient de la division courante est
diffrent de zro.


Par exemple, pour 123, on le divise par 10,
on obtient le quotient de 12 et un reste de 3
(premier chiffre trouv); ensuite, on divise
12 par 10, et on obtient un reste de 2
(deuxime chiffre trouv) et un quotient de
1. Ensuite, on divise 1 par 10; on obtient un
reste de 1 (troisime chiffre trouv) et un
quotient de zro. Et on arrte l ce
processus.
Lalgorithme pourrait tre comme suit:
void divisionchiffre(int n){
int quotient, reste;
quotient = n / 10;
while (quotient >= 10){
reste = n % 10;
printf(%d , reste);
n = quotient;
quotient = n / 10;
}
reste = n % 10;
printf(%d , reste);
}/* fin de la fonction




Analyse: Comme le corps de la boucle ne contient quun
nombre constant dinstructions lmentaires, sa complexit
est en O(1). Le problme consiste trouver combien de
fois la boucle while est rpte. Une fois cette information
connue, la complexit de tout lalgorithme est facile
driver. Dterminons donc ce nombre. Soit k litration k.
Nous avons ce qui suit:

itration k 1 2 3 .... k

valeur de n n/10 n/100 n/1000 n/10
k


Donc, litration k, la valeur courante de n est de n/10
k

Or, daprs lalgorithme, ce processus va sarrter
ds que
n/10
k
< 10
Autrement dit, ds que
n = n/10
k+1

En passant par le log,
k + 1 = log n
Autrement dit, le nombre ditrations effectues est
k = O(log n)
Par consquent, la complexit de lalgorithme ci-
dessus est en O(log n).


3. PGCD de deux nombres
int PGCD(int A, int B){
int reste;
reste = A % B;
while (reste !== 0)
{
A = B;
B = reste;
reste = A % B;
}
return(B);

} /* fin de la fonction */

Analyse: Encore une fois, le gros problme consiste
dterminer le nombre de fois que la boucle while
est rpte. Il est clair que dans ce cas, il y a lieu
normalement de distinguer les trois complexits.
En ce qui nous concerne, nous allons nous limiter
celle du pire cas. Pour ce qui est de celle du
meilleur cas, elle est facile dterminer; mais, en
revanche, celle du cas moyen, elle est plus
complique et ncessite beaucoup doutils
mathmatique qui sont en dehors de ce cours.
Pour ce faire, procdons comme suit pour la
complexit dans le pire cas:
Analyse PGCD suite
Avant de procder, nous avons besoin du rsultat suivant:

Proposition : Si reste = n % m alors reste < n/2
Preuve: Par dfinition, nous avons:
reste = n q.m; q >=1
reste <= n m (1)
On sait aussi que reste m -1 (2)
En additionnant (1) avec (2), on obtient:
2 reste < n 1
donc: reste < n / 2 CQFD

PGCD Suite
Durant les itrations de la boucle while, lalgorithme
gnre, travers la variable reste, la suite de
nombre de nombre {r0, r1, r2, r3 , ... },
reprsentant les valeurs que prennent les variable
n et m, o


De la proposition prcdente, on peut dduire


Par induction sur j, on obtient lune des deux
relations suivantes, selon la parit de lindice j
2 ; mod
; ;
1 1
1 0
> =
= =
+
j r r r
m r n r
j j j
2 /
1 1 +
=
j j
r r
PGCD suite
rj < r0 / 2
j/2
si j est pair
rj < r0 / 2
(j-1)/2
si j est impair


Dans les deux cas, la relation suivantes est vrifie:

rj < max(n,m) / 2
j/2








Ds que rj < 1, la boucle while se termine, cest--
dire ds que:
2
j/2
= max(n,m)



Par consquent, le nombre de fois que la boucle
while est rpte est gal

2log(max(n,m)+1) = O(log max(n,m)).

Comme le corps de cette boucle est en O(1), alors la
complexit de tout lalgorithme est aussi en

O(log max(n,m))



4. Recherche dun lment
dans un tableau tri
int recherche(int *tab, int C){
int sup, inf, milieu;
bool trouve;
inf = 0; sup = n; trouve = false;
while (sup >=inf && !trouve) {
milieu = (inf + sup) / 2;
if (C == tab[milieu])
trouve = true;
else if (C < tab[milieu])
sup = milieu -1;
else inf = milieu + 1;
if (!trouve)
return(0);
return(milieu)
} /* fin de la fonction */

Analyse: comme nous lavons dj mentionn
prcdemment, il y a lieu de distinguer
entre les trois diffrentes complexits.
Meilleur cas: Il nest pas difficile de voir que
le cas favorable se prsente quand la
valeur recherche C est au milieu du
tableau. Autrement dit, la boucle while ne
sera itre quune seule fois. Dans ce cas,
lalgorithme aura effectu un nombre
constant doprations; cest--dire en
O(1).

Pire cas: Ce cas se prsente quand
llment C nexiste pas. Dans ce cas, la
boucle while sera itre jusqu ce que la
variable sup < inf. Le problme est de
savoir combien ditrations sont ncessaires
pour que cette condition soit vrifie. Pour
le savoir, il suffit de constater, quaprs
chaque itration, lensemble de recherche
est divis par deux. Au dpart, cet intervalle
est gal sup (= n-1) inf (= 0) + 1 = n.
Itration intervalle de recherche
0 n
1 n/2
2 n/4
3 n/8
................................................
k n/ 2
k
On arrtera les itrations de la boucle while ds que
la condition suivante est vrifie

n/ 2
k
= 1 donc k = O(log n)

Autrement dit, la complexit de cet algorithme dans
le pire cas est en O(log n).

Cas moyen: Exercice



2. Exemples danalyse
dalgorithmes rcursifs
Dfinition: une fonction est rcursive si elle
fait appel elle-mme dune manire directe
ou indirecte
La rcursivit est une technique de
programmation trs utile qui permet de
trouver des solutions dune grande lgance
un certain nombre de problmes.
Attention!
lorsquelle mal utilise, cette subtilit
informatique peut crer un code totalement
inefficace.
Proprits dune rcursivit
1. La rcursivit (appels de la fonction elle-mme)
doit sarrter un moment donn (test darrt).
Autrement, lexcution va continuer indfiniment

void exemple()
{
cout << "La recursion\n";
exemple();
}

2. Un processus de rduction: chaque appel, on
doit se rapprocher de la condition darrt.

Exemple

int mystere (int n, int y){
if (n == 0) return y;
else return (mystere (n +1,y));
}
Pour n > 0, la condition darrt ne pourra pas
tre atteinte.
Tours de hanoi
void hanoi(int n, int i, int j, int k){
/*Affiche les messages pour dplacer n disques
de la tige i vers la tige k en utilisant la tige j */
if (n > 0)
{
hanoi(n-1, i, k, j)
printf (Dplacer %d vers %d, i,k);
hanoi(n-1, j, i, k)
}
} /* fin de la fonction */

Analyse de Hanoi
Pour dterminer la complexit de cette fonction,
nous allons dterminer combien de fois elle fait
appel elle-mme. Une fois ce nombre connu, il
est alors facile de dterminer sa complexit. En
effet, dans le corps de cette fonction, il a y a:
Un test
Deux appels elle mme
Deux soustractions
Une opration de sortie
En tout, pour chaque excution de cette fonction, il y
a 6 oprations lmentaires qui sont excutes.


Hanoi suite
Soit t(n) la complexit de la fonction hanoi(n,i,j,k). Il
nest pas difficile de voir, quelque que soit les
trois derniers paramtres, t(n-1) va reprsenter la
complexit de hanoi(n-1, -,-,-).
Par ailleurs, la relation entre t(n) et t(n-1) est comme
suit:
t(n) = t(n-1)+ t(n-1) + 6, si n > 0
t(0) = 1 (un seul test)
Autrement crit, nous avons:
t(n) = 2 t(n-1) + 6, si n > 0
t(0) = 1 (un seul test)

Hanoi suite
Pour rsoudre cette quation (de rcurrence), on
procde comme suit:

t(n) = 2 t(n-1) + 6
2 t(n-1) = 4 t(n-2) + 2.6
4t(n-2) = 8 t(n-3) + 4.6
...................................
2
(n-1)
t(1) = 2
n
t(0) + 2
(n-1)
.6
En additionnant membre membre, on obtient:

t(n) = 2
n
t(0) +6(1+2+4+ ... + 2
(n-1)

= 2
n
+ 6. (2
n-1
- 1)
= O(2
n
).

4. Nombres de Fibonacci

int Fibonacci(int n){
int temp;
if (n==0)
temp = 0;
else if (n==1)
temp = 1;
else temp = Fibonacci(n-1) + Fibonacci(n-2);
return (temp);
}


Soit t(n) la complexit de la fonction Fibonacci(n). Il
nest pas difficile de voir que t(n-1) va reprsenter
la complexit de Fibonacci(n-1) et t(n-2) celle de
Fibonacci(n-2).
Par ailleurs, la relation entre t(n), t(n-1) et t(n-2) est
comme suit:

t(n) = t(n-1)+ t(n-2) + 8, si n > 1
t(0) = 1 (un seul test)
t(1) = 2 (2 tests)

Pour rsoudre cette quation (aux diffrences), on va
procder comme suit:


Soit G(x) = Sum_{n=0}^{infini} t(n)x^n

Il est facile de voir:
Sum_{n>1} t(n)x^n = sum_{n>1} t(n-1)x^n +
sum_{n>1}t(n-2)x^n

Pour faire ressortir G(x), on fait comme suit:

Sum_{n>1} t(n)x^n = sum_{n=0}^{infini} t(n)x^n - t(0)x^0
t(1)x^1
= G(x) t(1) t(0)
Sum_{n>1} t(n-1)x^n = x sum_{n>1}^{infini} t(n-1)x^(n-1)
= x sum_{n>0}^{infini} t(n)x^(n)
= x sum_{n=0}^{infini} t(n)x^n t(0)x^0
= x(G(x) t(0))


Sum_{n>1} t(n-2)x^n = x^2 sum_{n>1}^{infini}
t(n-1)x^(n-2)
= x^2 sum_{n=0}^{infini}
t(n)x^(n)
= x^2G(x)
Par consquent, on obtient:

G(x) t(1) t(0) = xG(x) x x^2G(x)
G(x)(x^2 x -1) = x 3
G(x) = (x-3)/(x^2 x -1) = (x-3)/(x-a)(x-b)
O a = (1+racine(5))/2
b = (1-racine(5))/2
On peut aussi mettre
G(x) = f/(x-a) + g/(x-b)
On obtient
a = (1/(racine(5))
b = -(1/(racine(5))
G(x) = 1/(racine(5)(1/(x-a) 1/(x-b)

Rappels de mathmatiques:
1/(x-a) = \sum_{n=0}^{infini} (a^nx^n)
et
1/(x-b) = \sum_{n=0}^{infini} (b^nx^n);
Par consquent:
1/(x-a) - 1/(x-b) = \sum_{n=0}^{infini} (a^n-b^nx^n)
Par consquent, on obtient:
G(x)= 1/(racine(5))(sum_{n=0}^{infini} (a^n-
b^n)x^n) (rel1)
Et nous avons aussi:
G(x) = \sum_{n=0}^{infini} t(n)x^n (rel2)

Par identification entre (rel1) et (rel2), on obtient:

t(n) = 1/(racine(5)(a^n b^n)
= O(a^n) = O(((1+racine(5))/2)^n)
Exercice: Montrer dune manire plus
simple que la complexit T(n) de la fonction
Fibonacci est en O(2^n).
lments de complexit amortie
Complexit amortie
Dfinition
Dans lanalyse amortie, le temps mis pour effectuer
une suite doprations est pris comme la moyenne
arithmtique sur lensemble de ces oprations (ne
pas confondre avec lesprance mathmatique) .
Cela guarantie une borne suprieure sur le temps
moyen de chaque opration dans le pire cas.

Complexit amortie
La motivation de cette dmarche est que la
complexit dans le pire cas donne
gnralement une borne pessimiste car elle
ne considre que lopration la plus coteuse
sur lensemble des oprations restantes.
La mthode amortie consiste rpartir les
cuts sur toutes oprations de telle manire
que chacune delle aura un cot unique.
En dautres termes,
Lanalyse par rapport la complexit amortie
garantie la performance moyenne de chaque
opration dans le plus mauvais cas.

L'analyse amortie est diffrente de lanalyse en
moyenne. En effet,
dans l'analyse en moyenne, on cherche exploiter
le fait que le pire cas est peu probable en faisant
des hypothses sur la distribution des entres ou
sur les choix alatoires effectus dans
l'algorithme ;
dans l'analyse amortie, on cherche exploiter le
fait que le pire cas de l'algorithme ne peut pas se
produire plusieurs fois conscutivement, ou de
manire trop rapproche, quelle que soit l'entre.

Complexit amortie 3
Pensez comme si, lors de vos achats, vous aviez
dpens 10$ pour larticle 1, 20$ pour larticle 2 et
3 dollars pour larticle 3. Vous pourriez dire que le
cot de chaque article est de (20+10+3)3 = 11$.
On voit bien que le cot pour certains articles est
sous-sestim, aors quil est surestim pour
dautres. Ne pas confondre la complexit amortie
avec la complexit en moyenne (qui, elle, fait des
suppositions probabilistes). Dans le cas amorti,
aucune distribution probabiliste nest requise.
Cette mesure reprsente en quelque sorte la
complexit en moyenne du cas dfavorable.
Complexit amortie 4
Lapproche consiste affecter un cot artificiel
chaque opration dans la squence doprations. Ce
cot artificiel est appel cot amorti dune opration.

Le cot amorti dune opration est un artifice de
calcul qui souvent na aucune relation avec le cot
rel: souvent, ce cot peut tre nimporte quoi. La
seule proprit requise par un cot amorti est que le
cot rel total de toute la squence doprations doit
tre born par le cot total amorti de cette squence
doprations.

Autrement dit, pour les besoins de lanalyse, il sera
suffisant dutiliser le cot amorti au lieu de lactuel
cot de lopration.
Complexit amortie 5
Lanalyse amortie consiste estimer une borne
suprieure sur le cot total T(n) requis par une
squence de n oprations.
Quelques oprations, parmi cette squence,
peuvent avoir une cot norme et dautres, un cot
moindre. Lalgorithme gnre un cot T(n) pour
les n oprations.
Le cot amorti pour chaque opration est T(n)/n.
Complexit amortie 6
Il existe 3 mthodes pour dterminer la complexit
amortie dun algorithme. La diffrence rside
dans la manire dont le cot est assign aux
diffrentes oprations.
1. Mthode par aggrgation
2. Mthode comptable
3. Mthode du potentiel
Dans ce qui suit, nous allons illustrer chacune de ces
3 mthodes sur lexemple du compteur binaire.
Le problme du compteur binaire
tant donn un tableau de n bits, le problme
consiste, partir des bits 000000,
compter le nombre de fois que les bits
changent de valeur (de 0 1 et de 1 0),
chaque fois que la valeur 1 est ajoute. On
suppose que cette opration est rpte n fois.
Lalgorithme est alors comme suit:
Compteur binaire dordre 4
Analyse amortie
Une analyse nave montre queune squence
de n oprations gnre un cot de O(n^2).
En fait, lalgorithme INCREMENT, dans le
pire cas, a une complexit de O(n). Sil est
rpt n fois, alors la complexit est en
O(n^2). En effet, ce ne sont pas tous les bits
qui sont changs chaque itration.
1. Analyse par aggrgation
Combien de fois A[0] a t-il chang
Rponse: chaque fois
Combien de fois A[1] a t-il chang
Rponse: chaque 2 fois.
Combien de fois A[2] a t-il chang
Rponse: chaque 4 fois.
etc.
Le cot total pour changer A[0] est n,celui de
A[1] est floor(n/2), celui de A[2] est floor(n/4),
etc.
Par consquent, le cot total amorti est
T(n) = n + n2 +n/4++1
<= n\sum{i>=0} 1/2^I
<= 2n
Le cot amorti dune opration est
t(n) = T(n)/n = 2 = O(1)

2. Analyse comptable
Dans cette mthode, on assigne des cots
diffrents aux oprations: quelquunes
seront surcharges et dautres sous-
charges. La quantit dont nous chargeons
une opration est appele le cot amorti.
Quand une opration dpasse son cot rel,
la diffrence est affecte un autre objet, de
la structure de donnes comme un crdit.
Suite 1
Ce crdit est ensuite utilis plus tard pour payer
les oprations de complexit amortie moindre que
leur cot rel.
Le cot amorti dune opration peut donc tre vu
comme tant rparti entre le cot rel et le crdit
qui est soit dpos soit utilis. Cela est diffrent de
la mthode prcdente dans la mesure o les
oprations ont toutes le mme cot.
Pour satisfaire la proprit fondamentale dun cot
amorti, il y a lieu davoir le cot total amorti
comme une borne suprieure du cot rel. Par
consquent, on doit faire attention ce que le
crdit total doit toujours tre positif.
Suite 2
Dans le cas du problme du compteur binaire,
assignons un cut amorti de 2units pour initiliaser un
bit 1 (le 2 vient du fait quun bit est soit mis 1, soit
mis 0). Quand un bit est intilias, on utilise 1unit
(sur les 2units) pour payer linitiliasation proprement
dite, et nous plaons lautre unit sur ce bit comme
crdit.
En tout temps, tout bit 1 possde 1unit de crdit sur
lui. Donc, pas besoin de charger les bits quand ils
passent 0.

Suite 3
Le cot amorti de lalgorithme peut maintenant
tre dtermin comme suit:
Le cot de la rinitialisation de bits dans la boucle
while est pay par les units sur les bits initialiss.
Au plus un seul bit est initialis chaque itration
de lalgorithme, voir ligne 6, et par consquent le
cot amorti par opration est au plus de 2 units.
Le nombre de 1 dans le compteur nest jamais <0,
et donc la quantit de crdit est toujours >=0. Par
consquent, pour n oprations de lalgorithme, le
cot total amorti est en O(n), majorant le cot total
rel.
3. Mthode du potentiel

Au lieu de reprsenter le travail prpay
comme un crdit stock avec des objets
spcifiques dans la structure de donnes, la
mthode du potentiel de lanalyse amortie
reprsente ce travail comme un potentiel qui
peut tre libr pour payer des oprations
futures. Ce potentiel est associ toute la
structure de donnes, au lieu dune
opration comme cest le cas de la mthode
comptable.

Principe de la mthode
On commence avec une structure de
donnes D
0
sur laquelle n oprations sont
effectues. Pour chaque i =1,2,..,n, on pose
ci le cout rel de la ime opration et Di la
structure de donnes qui rsulte de
lapplication de la ime opration sur la
structure de donnes D_{i-1}. La fonction
potentielle qui associe chaque Di un
nombre (D
i
)
Suite 1
Le cot amorti d_i de la ime opration, par
rapport , est dfini comme suit:
d_i = c_i +\psy(D_i) - \psy(D_i-1)
Le cot amorti est le cot rel plus
laugmentation du potentiel d lopration
Le cot total amorti est donc:
\sum_{i=1}^n d_i = \sum_{i=1}^n
+\psy(D_n)-\psy(D_0)

Suite 2
Si nous pouvions dfinir une fonction\psy
telle que \psy(D_n)>= \psy(D_0), alors le
cot total amorti est un majorant sur le cot
total rel.
En pratique, on supose toujours
\psy)D_0) = 0.
Dfinissons la fonction potentielle comme suit:
= bi = nombre de 1 dans la structure de
donnes.

Dterminons le cot amorti de lalgorithme
INCREMENT
Supposons que la ime excution de INCREMENT a
chang t_i bits 0. Alors le cot total de cette
opration est au plus t_i +1, car en plus de cette
initialisation, elle peut aussi mettre un 1(le plus
gauche

Le nombre de 1 dans le tableau, aprs la ime
opration de INCREMENT est
bi <= b_{i-1}-t_i +1
La diffrence des potentiels est alors
\psy(D_i) - \psy(D_{i-1} <= b_{i-1}-t_i +1
- b_{i-1}
<= 1-t_i
Le cot amorti est donc

d_i = c_i + \psy(D_i) - \psy(D_{i-1}
<= (t_i + 1)+ (1-t_i)
= 2 = O(1)

Comme le compteur commence 0, alors
nous avons bien


Le cot total amorti est bien un majorant sur
le cot total rel. Le cot total amorti est
bien n*O(1) = O(n).


Quelques Rfrences
1. D. Rebane (2000): une introduction lanalyse
des algorithmes, ENAG dition.

2. Cormen et al. (1990): Algorithms, MacGraw
Hill.

3. J.M. Lina (2004): Analyse amortie des
algorithmes, ETS, Montral.

4. Data strctures, Algorithmes and applications,
Sartaj Sahni, Silicon Press, 1999.

Vous aimerez peut-être aussi