D'accord, refaisons cet exercice en C. Nous allons suivre les mêmes étapes que précédemment : écrire une fonction récursive pour calculer les nombres de Fibonacci, tester cette fonction pour de petites et grandes valeurs, observer les performances, et expliquer les résultats.
1. Écrire une fonction récursive fibo pour calculer le nème nombre de Fibonacci
Voici comment vous pouvez écrire une fonction récursive en C pour calculer le nème nombre de Fibonacci :
#include <stdio.h>
int fibo(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return fibo(n-1) + fibo(n-2);
}
}
int main() {
int n = 10; // Exemple avec n = 10
printf("Fibonacci de %d est %d\n", n, fibo(n));
return 0;
}
2. Lancer cette fonction pour de petites, puis de grandes valeurs de n
Pour de petites valeurs de n, la fonction fonctionne bien. Par exemple :
int main() {
printf("Fibonacci de 5 est %d\n", fibo(5)); // Affiche 5
printf("Fibonacci de 10 est %d\n", fibo(10)); // Affiche 55
return 0;
}
Pour de grandes valeurs de n, la fonction devient très lente. Par exemple :
int main() {
printf("Fibonacci de 30 est %d\n", fibo(30)); // Peut prendre un certain temps
printf("Fibonacci de 50 est %d\n", fibo(50)); // Peut prendre beaucoup de temps
return 0;
}
3. Que constatez-vous ?
Vous constatez que pour de grandes valeurs de n, la fonction devient extrêmement lente. Cela est dû au fait que la fonction récursive effectue de nombreux appels répétitifs, ce qui entraîne une complexité exponentielle.
4. Expliquer ce constat en listant tous les appels à votre fonction
Pour comprendre pourquoi la fonction devient lente, examinons les appels récursifs pour n=5 :
fibo(5)
fibo(4) + fibo(3)
fibo(3) + fibo(2) + fibo(2) + fibo(1)
fibo(2) + fibo(1) + fibo(1) + fibo(0) + fibo(1) + fibo(0)
fibo(1) + fibo(0) + fibo(1) + fibo(1) + fibo(0) + fibo(1) + fibo(0)
Vous pouvez voir que fibo(2) est calculé trois fois, fibo(1) est calculé cinq fois, etc. Ce phénomène s'aggrave à mesure que n augmente, car chaque appel à fibo(n) entraîne deux appels supplémentaires à fibo(n-1) et fibo(n-2), ce qui conduit à une explosion combinatoire des appels récursifs.
Pour résoudre ce problème, vous pouvez utiliser la mémoïsation (ou memoization en anglais), qui consiste à stocker les résultats des appels précédents pour éviter de les recalculer. Voici comment vous pouvez implémenter cela en C :
#include <stdio.h>
#define MAX 100
int memo[MAX];
int fibo_memo(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else if (memo[n] != -1) {
return memo[n];
} else {
memo[n] = fibo_memo(n-1) + fibo_memo(n-2);
return memo[n];
}
}
int main() {
for (int i = 0; i < MAX; i++) {
memo[i] = -1; // Initialiser le tableau de mémoïsation
}
int n = 50; // Exemple avec n = 50
printf("Fibonacci de %d est %d\n", n, fibo_memo(n));
return 0;
}
Avec cette version, les appels répétitifs sont évités, ce qui rend la fonction beaucoup plus efficace pour de grandes valeurs de n.