Vous êtes sur la page 1sur 19

Université USTHB – Bab-Ezzouar Bab-Ezzouar, 09 Février 2021

Faculté de l’Electronique et de l’Informatique, Département de l’Informatique Année universitaire 2020/2021


1ère année Master Informatique, Semestre 1 Semestre 1
Module : Conception et Complexité des Algorithmes
-------------------------------------------------------------------------------------------------------------------------------------------------------

Série de Travaux Pratiques n° 5 (TP n°5)

Algorithmes de Complexité temporelle


exponentielle 𝑶 𝒂𝒏 , 𝒂 > 1
Etude du problème de la suite de Fibonacci1

L’objet de ce TP est l’étude expérimentale de l’algorithme de résolution


du problème de ″la suite de Fibonacci″. On s’intéresse à l’algorithme récursif.
C’est un problème classique en informatique. On utilise les langages de
programmation C et Java.

La suite de Fibonacci est définie comme suit :

𝑓𝑖𝑏 𝑛 − 1 + 𝑓𝑖𝑏 𝑛 − 2 𝑠𝑖 𝑛 ≥ 2
𝑓𝑖𝑏 𝑛 =
1 𝑠𝑖 𝑛 = 0 𝑜𝑢 𝑛 = 1

Partie I : Développement de l’algorithme et du programme du


problème de la suite de Fibonacci avec le langage C
Dans cette partie, on développe un algorithme récursif et le programme
associé pour le problème de la suite de Fibonacci. .

1- Développer un algorithme récursif pour le calcul des éléments de la suite de


Fibonacci.
2- Calculer la complexité temporelle de cet algorithme, notée 𝑐𝑡(𝑛), en notations
exacte et asymptotique de Landau 𝑂 (Grand 𝑂).
3- Calculer la complexité spatiale de cet algorithme, notée 𝑐𝑠(𝑛), en notations
exacte et asymptotique de Landau 𝑂 (Grand 𝑂).
4- Ecrire avec le langage C le programme correspondant.
1
Né vers 1175 à Pise (Italie), son éducation s'est faite en grande partie à Béjaïa en Algérie, où son père
Guglielmo Bonacci était le représentant des marchands de la république de Pise. C'est dans cette ville portuaire,
qui est à l'époque un centre commercial et intellectuel, que Fibonacci commence son éducation en
mathématiques. Bien qu'on ne sache pas s'il est arabisant, il étudie notamment les travaux algébriques d'Al-
Khawarizmi {source : wikipédia].
ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 1 sur 19
5- Mesurer les temps d’exécution 𝑇 pour l’échantillon suivant de la variable 𝑛 et
compléter le tableau ci-dessous.

𝒏 … 10 11 12 … 20 21 22 … 30 31 32 … 62 63 64 … … …
𝑻

6- Développer un programme de mesure du temps d’exécution du programme


qui a en entrée les données de l’échantillon ci-dessus et en sortie les temps
d’exécution. Les données et les mesures du temps sont à enregistrer dans des
tableaux notés respectivement 𝑡𝑎𝑏1 𝑒𝑡 𝑡𝑎𝑏2.
7- Représenter par un graphe, noté 𝐺𝑐𝑡 (𝑛), les variations de la fonction de la
complexité temporelle en fonction de 𝑛 ; et par un autre graphe, noté 𝐺𝑇 (𝑛),
les variations du temps d'exécution 𝑇(𝑛) en fonction de 𝑛. Utiliser pour cela
un logiciel graphique tel que excel.
8- Interprétation des résultats :
8.a- Que remarque-t-on sur les données de l'échantillon et sur les mesures
obtenues ? Peut-on déduire, même de façon approximative, une fonction 𝑇(𝑛)
reliant 𝑇 𝑒𝑡 𝑛 ; c'est-à-dire une fonction 𝑇(𝑛) permettant de déterminer
directement la valeur de 𝑇 à partir de 𝑛.
Ind : comparer chaque nombre 𝑛 avec le suivant ; et chaque mesure du temps
avec la suivante.
8.b- Comparer entre la complexités théorique et la complexité
expérimentale (çàd., les mesurs expérimentales). Les prédictions théoriques
sont-elles compatibles avec les mesures expérimentales ?

Partie II : Développement de l’algorithme et du programme du


problème de la suite de Fibonacci avec le langage Java
Dans cette partie, on refait le travail fait en partie I avec le langage Java.

9- Refaire les questions 1 à 8 de la partie I en utilisant le langage Java.

Partie III : Rédaction d’un rapport de travail

Dans cette partie, on rédige un rapport décrivant le travail réalisé dans les
2 parties précédentes.

10- Rédiger un rapport décrivant le travail réalisé dans les 2 parties précédentes.

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 2 sur 19
Rem : Il est intéressant de développer une version itérative pour cet
algorithme.

NB : - Le travail doit être fait en groupes de 3 à 4 étudiants.


- Le rapport du travail doit être remis dans un délai de 15 jours.
- Ce travail est noté.

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 3 sur 19
Le Corrigé du TP n°5

Partie I : Développement de l’algorithme et du programme du


problème de la suite de Fibonacci avec le langage C
Dans cette partie, on développe un algorithme récursif et le programme
associé pour le problème de la suite de Fibonacci. .

1- Développer un algorithme récursif pour le calcul des éléments de la suite de


Fibonacci.

Solution :
L’algorithme récursif du problème de calcul des éléments de la suite de
Fibonacci, noté "Fibonacci_réc", s’écrit simplement comme s’énonce sa
définition. Il faut noter que l’on a 2 appels récursifs avec 2 paramètres
successifs : 𝑛 − 1 𝑒𝑡 𝑛 − 2 ; ce qui n’est pas le cas de l’algorithme récursif
du problème des tours de Hanoi (voir TP n° 4) où l’on a aussi 2 appels récursifs
mais avec le même paramètre : n − 1 . Il est présenté sur la figure 1 ci-dessous
(les instructions sont numérotées en rouge de 1 à 9).

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 4 sur 19
Algorithme Fibonacci_réc ; //Algorithme du problème de calcul des éléments
//de la suite de Fibonacci
Var n, res : entier ;

Début
//Partie 1: Lecture des données
1 ecrire ("\nDonner le nombre n = ");
2 lire (n);

//Partie 2: Traitement
3 res = fib(n) ; //appel de la fonction fib(n)

//Partie 3: Sortie des résultats


4 ecrire ("La valeur de la suite de Fibonacci pour n = ", n, " est res = ", res);
Fin. //fin de l’algorithme Fibonacci

//Définition de la fonction fib(int n)


int fib(int n)
Début
5 si (n = 0)
6 alors retourner 1;
7 sinon si (n = 1)
8 alors retourner 1;
9 sinon retourner fib(n-1) + fib(n-2) ;
//2 appels récursifs avec 2 paramètres successifs : (n-1) et (n-2)
finsi ;
finsi ;
Fin ; //fin de la fonction fib(int n)

Figure 1. Fibonacci_réc : Algorithme récursif du problème de calcul


des éléments de "la suite de Fibonacci".
(Il utilise la fonction récursive fib(int n))

2- Calculer la complexité temporelle de cet algorithme, notée 𝑐𝑡(𝑛), en notations


exacte et asymptotique de Landau 𝑂 (Grand 𝑂).

Solution :
Rappels : La définition de la complexité temporelle d’un algorithme itératif est
la même que celle d’un algorithme itératif. On reprend à titre de rappel la
définition présentée au chapitre 2.

Définition : La complexité temporelle d’un algorithme désigne la mesure du


temps nécessaire pour son exécution sur une machine RAM. Elle est donnée

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 5 sur 19
sous la forme d’une fonction, en notations exacte et/ou asymptotique, dont les
variables sont les données en entrée de l’algorithme.

Rem 1 : L’unité de mesure du temps d’exécution est le nombre d’instructions


exécutées par cet algorithme.

Rem 2 : Il faut préciser que la notation exacte est rarement utilisée. C’est la
notation asymptotique de Landau qui est couramment utilisée.

Les règles suivantes permettent de calculer effectivement la complexité


temporelle d’un algorithme récursif (voir les TPs n°2 et n°3 pour le cas des
algorithmes itératifs) :

1- La complexité temporelle est calculée en fonction des données en entrée de


l'algorithme.
2- Le calcul de la complexité temporelle peut se ramener au calcul du nombre
d’instructions exécutées par cet algorithme qu’on appelle aussi fréquence
d’exécution des instructions de l’algorithme car la fonction T(n) qui mesure le
temps d’exécution d’un algorithme et la fonction F(n) qui mesure le nombre
d’instructions exécutées par cet algorithme appartiennent à la même classe de
complexité (voir la remarque déjà donnée dans le corrigé du TP1).
3- les principales classes de complexité sont :
𝑂 𝑛 , 𝑂 𝑛2 , 𝑂 𝑛3 , 𝑂 𝑙𝑜𝑔 𝑛 , 𝑂 𝑛𝑙𝑜𝑔 𝑛 , 𝑂 𝑎𝑛 , 𝑒𝑡𝑐.
4- Pour calculer la complexité temporelle d'un algorithme, on doit :
a) calculer les fréquences d'exécutions de chacune des instructions de
l'algorithme ;
b) Dans le cas d’une instruction conditionnelle complète ayant les 2
branches alors et sinon, on doit calculer la somme de la fréquence de la
condition de l’instruction conditionnelle et le maximum des fréquences
entre ses 2 branches dans le pire cas ou le minimum des fréquences
dans le meilleur cas (car une seule branche est exécutée).
c) Dans le cas d’une instruction de répétition (pour, tant que ou répéter),
on doit calculer la somme de la fréquence de la condition de
l’instruction de la répétition et des fréquences des instructions
contenues dans le corps (ou le bloc) de l’instruction de la répétition ;
d) Calculer la somme des fréquences des instructions de l’algorithme.
5- Généralement, le calcul de la complexité temporelle exacte n'est pas possible
car cela dépend des données en entrée de l’algorithme, et on se restreint alors au
calcul des complexités au pire cas, au moyen cas et au meilleur cas. La
complexité au pire cas est celle qui est la plus utilisée.
ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 6 sur 19
6- Les instructions exécutables correspondent aux opérations exécutables par le
processeur de manière indivisible :
- les opérations arithmétiques (+, -, *, /) ;
- les opérations de condition (==, !=, <, <=, >, >=) ;
- les opérations d'entrée/sortie (lire(), ecrire()).
7- Les fonctions prédéfinies comme sin, cos, log, modulo, etc. sont supposées se
comporter comme des opérations exécutables par le processeur de manière
indivisible (cette hypothèse ne change pas la complexité de l’algorithme).
8- On suppose que toutes les instructions prennent la même durée de temps
d'exécution, ce qui permet de faire l'addition de leurs fréquences d'exécutions (là
aussi, cette hypothèse ne change pas la complexité de l’algorithme).
9- Le meilleur cas d’un algorithme correspond au nombre minimal du nombre
d’instructions exécutées par cet algorithme alors que le pire cas correspond au
nombre maximal du nombre d’instructions exécutées.
10- Avec les algorithmes récursifs, on doit tenir compte de chaque appel récursif
d'une fonction qui génère de façon dynamique, et donc de façon transparente au
programmeur, l'exécution de la même fonction avec de nouveaux paramètres
d'appels et de nouvelles variables locales de la fonction. Dans la pratique, on
calcule le nombre d'appels récursifs en résolvant une équation de récurrence.

Soit 𝐿 le nombre d'instructions de l'algorithme récursif Fibonacci_réc (voir ci-


dessus) et soit 𝑛𝑏𝑥 la somme des fréquences d'exécutions de toutes les
instructions de cet algorithme.

On a : 𝐿 = 9 instructions.

Pour calculer 𝑛𝑏𝑥, on utilise les fréquences d'exécutions 𝑓𝑖 de chacune des


𝐿 = 9 instructions de l'algorithme Fibonacci_réc comme il est montré sur le
tableau suivant :

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 7 sur 19
N° Instruction Ii Fréquence d'exécution fi

//Algorithme principal
1 ecrire("Donner le nombre n ="') ; 𝑓1 = 1

2 lire(n) ; 𝑓2 = 1

3 res = fib(n) ; 𝑓3 = 𝐻(𝑛) + 2

4 ecrire ("La valeur de la suite de Fibonacci


pour n = ", n, " est res = ", res) ; 𝑓4 = 1

//la fonction int fib(int n)


5 si (n = 0) 𝑓5 = 1

1 𝑠𝑖 𝑛 = 0
6 alors retourner 1 ; 𝑓6 = 0 𝑠𝑖 𝑛 = 1
0 𝑠𝑖 𝑛 ≥ 2

0 𝑠𝑖 𝑛 = 0
7 sinon si (n = 1) 𝑓7 = 1 𝑠𝑖 𝑛 = 1
1 𝑠𝑖 𝑛 ≥ 2

0 𝑠𝑖 𝑛 = 0
8 alors retourner 1 ; 𝑓8 = 1 𝑠𝑖 𝑛 = 1
0 𝑠𝑖 𝑛 ≥ 2

9 sinon retourner fib(n-1) + fib(n-2) 


0 𝑠𝑖 𝑛 = 0
𝑓9 = 0 𝑠𝑖 𝑛 = 1
𝐻 𝑛−1 +𝐻 𝑛−2 +6 𝑠𝑖 𝑛 ≥ 2
finsi ;
finsi ;

Figure 2. Tableau des fréquences d'exécutions des instructions de


l'algorithme Fibonacci_réc.

Commentaire explicatif :
1- L’instruction d’appel de fonction n°3 : res = fib(n)
Cette instruction est une affectation d’un appel de la fonction fib(n) à une
variable. C’est une instruction complexe composée de 3 instructions :
1- Une instruction d’appel de la fonction : fib(n).
2- L’exécution de la fonction récursive fib(n).
3- Une instruction d’affectation : res = fib(n).
ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 8 sur 19
Les 2 instructions d’appel de la fonction récursive et d’affectation sont
comptées chacune 1 fois comme des opérations exécutables par le processeur de
manière indivisible.

La complexité temporelle de la fonction récursive fib(n) est notée H(n).


Autrement dit, la fonction H(n) désigne le nombre d’instructions exécutées par
la fonction récursive fib(n).

Il en résulte :
𝑓3 (𝑛) = 𝐻(𝑛) + 2

2- L’instruction d’appel de fonction n°9 : retourner fib(n-1) + fib(n-2)


Cette instruction est un retour de résultat de la fonction fib(n). C’est une
instruction complexe composée de 8 instructions :
1- 2 instructions arithmétiques de soustraction : (n-1) et (n-2).
2- 2 instructions d’appel de fonction : fibt(n-1) et fib(n-2).
3- 1 instruction arithmétique d’addition : fib(n-1) + fib(n-2).
4- 1 instruction de retour de fonction : retourner fib(n-1) + fib(n-2)
5- L’exécution de 2 fonction récursives : fib(n-1) et fib(n-2).

Les 6 premières instructions sont comptées chacune 1 fois comme des


opérations exécutables par le processeur de manière indivisible.

La complexité temporelle de la fonction fib(n-1) est H(n-1) car l’appel de la


fonction fib s’effectue avec le paramètre (n-1).

De même, la complexité temporelle de la fonction fib(n-2) est H(n-2) car


l’appel de la fonction fib s’effectue avec le paramètre (n-2).

Il en résulte :
0 𝑠𝑖 𝑛 = 0
𝑓9 = 0 𝑠𝑖 𝑛 = 1
𝐻 𝑛−1 +𝐻 𝑛−2 +6 𝑠𝑖 𝑛 ≥ 2

Du fait que l’algorithme comporte une fonction récursive, le calcul de la somme


des fréquences d'exécutions des instructions de l'algorithme est scindée en 3
étapes :
1- L’algorithme principal de Fibonacci_réc.
2- La fonction fib(n).
3- Le calcul de la complexité temporelle en notations exacte et/ou
asymptotique.
ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 9 sur 19
1- Etape 1 : Algorithme principal de Fibonacci_réc (instructions 1 à 4)
1-a) On calcule les fréquences des 4 instructions de l’algorithme principal
(instructions 1 à 4) :

Cette étape est traitée dans le tableau des fréquences d'exécutions des
instructions ci-dessus.

1-b) On calcule la somme de ces fréquences :


4

𝑛𝑏𝑥 𝑛 = 𝑓𝑖 = 𝑓1 + 𝑓2 + 𝑓3 + 𝑓4
𝑖=1

𝑛𝑏𝑥 𝑛 = 1 + 1 + 𝐻 𝑛 + 2 + 1

𝑛𝑏𝑥 𝑛 = 𝐻 𝑛 + 5 (1)

2- Etape 2 : La fonction fib(n) (instructions 5 à 9)


2-a) On calcule les fréquences des 5 instructions de la fonction
fib(n) (instructions 5 à 9) :

Cette étape est traitée dans le tableau des fréquences d'exécutions des
instructions ci-dessus.

2-b) On calcule 𝑯 𝒏 la somme des fréquences des 5 instructions de la


Fonction fib(n) (instructions 5 à 9) :
9

𝐻 𝑛 = 𝑓𝑖 = 𝑓5 + 𝑓6 + 𝑓7 + 𝑓8 + 𝑓9
𝑖=5

𝐻 𝑛 =
1 + 1 + 0 + 0 + (0) 𝑠𝑖 𝑛 = 0
1 + 0 + 1 + 1 + (0) 𝑠𝑖 𝑛 = 1
1 + 0 + 1 + 0 + (𝐻 𝑛 − 1 + 𝐻 𝑛 − 2 + 6) 𝑠𝑖 𝑛 ≥ 2

2 𝑠𝑖 𝑛 = 0
𝐻 𝑛 = 3 𝑠𝑖 𝑛 = 1 (2)
𝐻 𝑛−1 +𝐻 𝑛−2 +8 𝑠𝑖 𝑛 ≥ 2

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 10 sur 19
Rem 3 : On déduit à partir de l’équation (2) que les conditions initiales
𝑯(𝟎) = 𝟐 et 𝑯(𝟏) = 𝟑 correspondent aux conditions terminales de la fonction
récursive fib(n).

Rem 4 : On déduit aussi à partir de l’équation (2) que le meilleur cas correspond
à 𝑛 = 0 et le pire cas correspond au maximum de la valeur de 𝑛, 𝑛 >= 2. La
valeur 𝑛 = 1 est un cas intermédiaire entre ces 2 cas extrêmes (de même que
toutes les valeurs 𝑖, 1 ≤ 𝑖 ≤ (𝑛 − 1)) .

2-c) On résout l’équation de récurrence linéaire (2) :


Cette équation de récurrence linéaire non-homogène à coefficients
constants a été résolue dans la série TD 3 relative au chapitre 3 (voir
l’exercice 7 pour l’équation non-homogène et l’exercice 4 pour l’équation
homogène associée).

On rappelle que la solution de cette équation est :


𝟔+𝟓 𝟓 𝟏+ 𝟓 𝒏 𝟏𝟗− 𝟓 𝟏− 𝟓 𝒏
𝐻 𝒏 =( )( ) +( )( ) −𝟖 ∀𝒏≥𝟎 (3)
𝟓 𝟐 𝟓+ 𝟓 𝟐

3- Etape 3 : Calcul de la complexité temporelle 𝒄𝒕(𝒏)


En remplaçant (3) dans (1), on a :

𝑛𝑏𝑥 𝑛 = 𝐻 𝑛 + 5

6+5 5 1+ 5 𝑛 19− 5 1+ 5 𝑛
𝑛𝑏𝑥 𝑛 = ( ( )( ) +( )( ) −8)+5 ∀𝑛≥0
5 2 5+ 5 2

6+5 5 1+ 5 𝑛 19− 5 1+ 5 𝑛
𝑛𝑏𝑥 𝑛 = ( )( ) +( )( ) −3 ∀𝑛≥0 (4)
5 2 5+ 5 2

a- En notation exacte :
On a :
𝑐𝑡 𝑛 = 𝑛𝑏𝑥 𝑛

6+5 5 1+ 5 𝑛 19− 5 1− 5 𝑛
𝑐𝑡 𝑛 = ( )( ) +( )( ) −3 ∀𝑛≥0
5 2 5+ 5 2

b- En notation asymptotique O :

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 11 sur 19
On a :
1+ 5 𝑛
𝑐𝑡 𝑛 = 𝑂(( ) )
2
//Voir le chapitre 1 et la série TD n°1 pour l’écriture des fonctions en notation
//asymptotique.
𝟏− 𝟓 𝟏− 𝟓 𝒏
//(Ind : On a : 𝟓 ≈ 𝟐. 𝟐𝟑𝟔 −𝟏<( )<0 −𝟏 < ( ) < 1)
𝟐 𝟐

En conséquence, la complexité temporelle, notée 𝑐𝑡(𝑛), de l'algorithme récursif


Fibonacci_réc est :
6+5 5 1+ 5 𝑛 19− 5 1+ 5 𝑛
( )() + ( 5+ )( ) − 3 𝑒𝑛 𝑛𝑜𝑡𝑎𝑡𝑖𝑜𝑛 𝑒𝑥𝑎𝑐𝑡𝑒
5 2 5 2
𝑐𝑡 𝑛 = 𝑛 (5)
1+ 5
𝑂( ) 𝑒𝑛 𝑛𝑜𝑡𝑎𝑡𝑖𝑜𝑛 𝑎𝑠𝑦𝑚𝑝𝑡𝑜𝑡𝑖𝑞𝑢𝑒
2

3- Calculer la complexité spatiale de cet algorithme, notée 𝑐𝑠(𝑛), en notations


exacte et asymptotique de Landau 𝑂 (Grand 𝑂).

Solution :
Rappel : La définition de la complexité spatiale d’un algorithme itératif est la
même que celle d’un algorithme itératif. On reprend à titre de rappel la
définition déjà présentée au chapitre 2.

Définition : La complexité spatiale d'un algorithme désigne la mesure de


l’espace mémoire nécessaire pour enregistrer en mémoire centrale les
instructions et les données de cet algorithme lors de son exécution sur une
machine RAM. Elle est donnée sous la forme d’une fonction, en notations
exacte et/ou asymptotique, dont les variables sont les données en entrée de
l’algorithme.

Rem 1 : L’unité de mesure de l’espace mémoire est le nombre de mots


mémoire.

Rem 2 : Il faut préciser que la notation exacte est rarement utilisée. C’est la
notation asymptotique de Landau qui est couramment utilisée.

Les règles suivantes permettent de calculer effectivement la complexité spatiale


d’un algorithme récursif (voir les TPs n° 2 et n°3 qui présentent les cas des
algorithmes itératifs) :

1- La complexité spatiale est calculée en fonction des données en entrée de


l'algorithme.
ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 12 sur 19
2- Les classes de complexité les plus utilisées sont :
𝑂 𝑛 , 𝑂 𝑛2 , 𝑂 𝑛3 , 𝑂 𝑛 , 𝑂 𝑙𝑜𝑔 𝑛 , 𝑂 𝑛𝑙𝑜𝑔 𝑛 , 𝑂 𝑎𝑛 , 𝑒𝑡𝑐.
3- Généralement, le calcul de la complexité spatiale des algorithmes itératifs ne
pose pas de problèmes ; il se limite au comptage des instructions et des
données de l’algorithme.
4- La complexité spatiale d’une fonction récursive incluse dans un algorithme
récursif doit tenir compte de chaque appel récursif de cette fonction qui
génère de façon dynamique, et donc de façon transparente au programmeur,
l'allocation d'un espace mémoire géré en une pile en mémoire centrale pour
sauvegarder les paramètres d'appels de cette fonction et de ses variables
locales. Ce calcul aboutit à une équation de récurrence dont le terme général
représente la complexité spatiale de la fonction récursive.
5- Les conditions initiales de l’équation de récurrence correspondent à l’espace
mémoire nécessaire pour réaliser les conditions terminales de la fonction
récursive.
6- L'unité de mesure de la complexité spatiale est le mot mémoire qui est un
nombre multiple d'octets, mais généralement en puissance de 2 (1, 2, 4 ou 8
octets). On suppose qu'une instruction occupe 1 mot mémoire et qu’une
donnée de type scalaire (entier, réel, logique ou caractère) occupe aussi un
mot mémoire.

On rappelle que l’algorithme récursif est comme suit :

- L’algorithme récursif Fibonacci_réc :

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 13 sur 19
Algorithme Fibonacci_réc ; //Algorithme du problème de calcul des éléments
//de la suite de Fibonacci
Var n, res : entier ;

Début
//Partie 1: Lecture des données
1 ecrire ("\nDonner le nombre n = ");
2 lire (n);

//Partie 2: Traitement
3 res = fib(n) ; //appel de la fonction fib(n)

//Partie 3: Sortie des résultats


4 ecrire ("La valeur de la suite de Fibonacci pour n = ", n, " est res = ", res);
Fin. //fin de l’algorithme Fibonacci

//Définition de la fonction fib(int n)


int fib(int n)
Début
5 si (n = 0)
6 alors retourner 1;
7 sinon si (n = 1)
8 alors retourner 1;
9 sinon retourner fib(n-1) + fib(n-2) ;
//2 appels récursifs avec 2 paramètres successifs : (n-1) et (n-2)
finsi ;
finsi ;
Fin ; //fin de la fonction fib(int n)

Figure 1. Fibonacci_réc : Algorithme récursif du problème de calcul


des éléments de "la suite de Fibonacci".
(Il utilise la fonction récursive fib(int n))

Pour calculer la complexité spatiale, notée 𝑐𝑠(𝑛), de l’algorithme récursif


Fibonacci_réc, on procède en 4 étapes :

1- Calculer le nombre d’instructions de l’algorithme (algorithme principal et


fonction récursive) et l’espace mémoire nécessaire pour leur
enregistrement en mémoire centrale.
2- Calculer le nombre des données globales de l’algorithme principal et
l’espace mémoire nécessaire pour leur enregistrement en mémoire
centrale. Il faut distinguer entre les données scalaires (ou élémentaires) et
les données composées.

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 14 sur 19
3- Calculer le nombre des données locales de la fonction récursive
(paramètres de la fonction et ses variables locales) et l’espace mémoire
nécessaire pour leur enregistrement dans une pile en mémoire centrale. Il
faut distinguer entre les données scalaires (ou élémentaires) et les données
composées.
4- Calculer la complexité spatiale en notations exacte et/ou asymptotique.

1- Etape 1 : Calcul de l’espace mémoire nécessaire pour enregistrer les


instructions de l’algorithme (algorithme principal et fonction récursive)

Soit 𝐿 nombre d'instructions de l'algorithme Fibonacci_réc (algorithme


principal et fonction récursive) (voir l’algorithme, ci-dessus) et soit 𝑀𝐼 l'espace
mémoire occupé par ces instructions.
On a :
𝐿 = 9 𝑖𝑛𝑠𝑡𝑟𝑢𝑐𝑡𝑖𝑜𝑛𝑠 𝑀𝐼 = 9 //en mots mémoires
//4 instructions pour l’algorithme principal
//5 instructions pour la fonction récursive fib(n)
//1 instruction occupe 1 mot mémoire (par hypothèse)

2- Etape 2 : Calcul de l’espace mémoire nécessaire pour enregistrer les


données globales de l’algorithme

Soit 𝑁𝐷1 le nombre des données globales de type scalaire de l'algorithme


principal Fibonacci_réc et soit 𝑀𝐷1 l’espace mémoire occupé par ces données.

On a :
𝑁𝐷1 = 2 𝑑𝑜𝑛𝑛é𝑒𝑠 de type scalaire (entier) : 𝑛 𝑒𝑡 𝑟𝑒𝑠 ;

𝑀𝐷1 = 2 //en mots mémoires


//1 donnée occupe 1 mot mémoire (par hypothèse)

Rem 3 : L’algorithme principal ne comporte pas de données composées.

3- Etape 3 : Calcul de l’espace mémoire nécessaire pour enregistrer les


données locales de la fonction récursive fib(n)

Chaque appel de la fonction récursive fib(n) génère l’allocation d’un espace


mémoire noté 𝐺(𝑛) vérifiant l’équation de récurrence suivante :

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 15 sur 19
𝐺 𝑛 =1+𝐺 𝑛−1 ∀𝑛 ≥ 2
𝐺 0 =1 (6)
𝐺 1 =1
où,
- 𝐺(𝑛 − 1) correspond à l’espace mémoire des données locales (paramètres
et variables locales) de la fonction fib(n-1) (incluse dans la définition de
fib(n)).
- La constante 1 correspond à correspond à l’espace mémoire nécessaire
pour enregistrer le paramètre de la fonction récursive fib(n) (ici, on a 1
seul paramètres : 𝑛 et aucune variable locale).
- 𝐺 0 = 1 est la condition initiale de l’équation de récurrence et
correspond à l’espace mémoire nécessaire pour réaliser les conditions
terminales de la fonction récursive fib(n) (ici, la condition terminale est
fib(0)) qui nécessite un espace mémoire pour enregistrer le paramètre
𝑛 = 0).
- 𝐺 1 = 1 est la condition initiale de l’équation de récurrence et
correspond à l’espace mémoire nécessaire pour réaliser les conditions
terminales de la fonction récursive fib(n) (ici, la condition terminale est
fib(1)) qui nécessite un espace mémoire pour enregistrer le paramètre
𝑛 = 1).

La solution de cette équation de récurrence est comme suit (voir le chapitre 3 et


la série TD n°3) :

𝑛 𝑠𝑖 𝑛 ≥ 1
𝐺 𝑛 = (7)
1 𝑠𝑖 𝑛 = 0

Rem 4 : Il y a dans l’algorithme Fibonacci_réc 2 appels récursifs à la fonction


fib au niveau de la même instruction n°9 :

1- fib(n-1) //(instruction n° 9)

2- fib(n-2) //(instruction n° 9)

Cependant, on n’a pas besoin de sauvegarder en même temps, dans une pile,
les données locales (paramètres et variables locales) de ces 2 fonctions car la
2ème fonction fib(n-2) ne commence son exécution qu’après la terminaison de
l’exécution de la 1ère fonction fib(n-1), soit après que les données de cette
dernière soient entièrement dépilées.

Rem 5 : Il faut rappeler que l’allocation de l’espace mémoire pour la sauvegarde


temporaire des paramètres et des données locales de la fonction récursive fib(n)
ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 16 sur 19
(mais également de même une fonction itérative) s’effectue "de manière
dynamique", c'est-à-dire en cours d’exécution du programme. La fonction
𝐺(𝑛) dans la relation (7) exprime bien cet aspect dynamique de l’allocation
mémoire :

1- quand 𝑛 ≥ 1, on réserve 𝑛 mots mémoires ;

2- quand 𝑛 = 0, on réserve 𝑛 mots mémoires.

4- Etape 4 : Calcul de la complexité spatiale 𝒄𝒔(𝒏) en notations exacte et/ou


asymptotique

Soit 𝑀(𝑛) l’espace mémoire nécessaire pour enregistrer les instructions et les
données de l’algorithme.
On a :
𝑀(𝑛) = 𝑀𝐼 + 𝑀𝐷1 + 𝐺(𝑛)

9 + (2) + 𝑛 𝑠𝑖 𝑛 ≥ 1
𝑀 𝑛 = //en mots mémoires
9 + (2) + 1 𝑠𝑖 𝑛 = 0

𝑛 + 11 𝑠𝑖 𝑛 ≥ 1
𝑀 𝑛 = //en mots mémoires
12 𝑠𝑖 𝑛 = 0

a - En notation exacte :
On a :
𝑐𝑠 𝑛 = 𝑀 𝑛
𝑛 + 11 𝑠𝑖 𝑛 ≥ 1
𝑐𝑠 𝑛 =
12 𝑠𝑖 𝑛 = 0

b- En notation asymptotique O :
On a :
𝑂(𝑛) 𝑠𝑖 𝑛 ≥ 1
𝑐𝑠 𝑛 =
𝑂(1) 𝑠𝑖 𝑛 = 0
//Voir le chapitre 1 et la série TD n°1 pour l’écriture des fonctions
//en notation asymptotique.

En conséquence, la complexité spatiale, notée 𝑐𝑠(𝑛), de l'algorithme récursif


Fibonacci_réc est :

𝑛 + 11 𝑠𝑖 𝑛 ≥ 1
𝑒𝑛 𝑛𝑜𝑡𝑎𝑡𝑖𝑜𝑛 𝑒𝑥𝑎𝑐𝑡𝑒
12 𝑠𝑖 𝑛 = 0
𝑐𝑠 𝑛 = 𝑂(𝑛) 𝑠𝑖 𝑛 ≥ 1 (8)
𝑒𝑛 𝑛𝑜𝑡𝑎𝑡𝑖𝑜𝑛 𝑎𝑠𝑦𝑚𝑝𝑡𝑜𝑡𝑖𝑞𝑢
𝑂(1) 𝑠𝑖 𝑛 = 0
ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 17 sur 19
4- Ecrire avec le langage C le programme correspondant.

Solution :
A traiter par les étudiants

5- Mesurer les temps d’exécution 𝑇 pour l’échantillon suivant de la variable 𝑛 et


compléter le tableau ci-dessous.

𝒏 … 10 11 12 … 20 21 22 … 30 31 32 … 62 63 64 … … …
𝑻

Solution :
A traiter par les étudiants

6- Développer un programme de mesure du temps d’exécution du programme


qui a en entrée les données de l’échantillon ci-dessus et en sortie les temps
d’exécution. Les données et les mesures du temps sont à enregistrer dans des
tableaux notés respectivement 𝑡𝑎𝑏1 𝑒𝑡 𝑡𝑎𝑏2.

Solution :
A traiter par les étudiants

7- Représenter par un graphe, noté 𝐺𝑐𝑡 (𝑛), les variations de la fonction de la


complexité temporelle en fonction de 𝑛 ; et par un autre graphe, noté 𝐺𝑇 (𝑛),
les variations du temps d'exécution 𝑇(𝑛) en fonction de 𝑛. Utiliser pour cela
un logiciel graphique tel que excel.

Solution :
A traiter par les étudiants

8- Interprétation des résultats :


8.a- Que remarque-t-on sur les données de l'échantillon et sur les mesures
obtenues ? Peut-on déduire, même de façon approximative, une fonction 𝑇(𝑛)
reliant 𝑇 𝑒𝑡 𝑛 ; c'est-à-dire une fonction 𝑇(𝑛) permettant de déterminer
directement la valeur de 𝑇 à partir de 𝑛.
Ind : comparer chaque nombre 𝑛 avec le suivant ; et chaque mesure du temps
avec la suivante.

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 18 sur 19
8.b- Comparer entre la complexités théorique et la complexité
expérimentale (çàd., les mesurs expérimentales). Les prédictions théoriques
sont-elles compatibles avec les mesures expérimentales ?

Solution :
A traiter par les étudiants

Partie II : Développement de l’algorithme et du programme du


problème de la suite de Fibonacci avec le langage Java
Dans cette partie, on refait le travail fait en partie I avec le langage Java.

9- Refaire les questions 1 à 8 de la partie I en utilisant le langage Java.

Solution :
A traiter par les étudiants

Partie III : Rédaction d’un rapport de travail

Dans cette partie, on rédige un rapport décrivant le travail réalisé dans les
2 parties précédentes.

10- Rédiger un rapport décrivant le travail réalisé dans les 2 parties précédentes.

Solution :
A traiter par les étudiants

Rem : Il est intéressant de développer une version itérative pour cet


algorithme.

NB : - Le travail doit être fait en groupes de 3 à 4 étudiants.


- Le rapport du travail doit être remis dans un délai de 15 jours.
- Ce travail est noté.

ère
1 année Master Informatique
Module : Conception et Complexité des Algorithmes, Série de Travaux Pratiques n° 5 Page 19 sur 19

Vous aimerez peut-être aussi