Fiche Récursivité
Fiche de Révision : La Récursivité en C
1. Introduction à la Récursivité
La récursivité est une technique de programmation où une fonction s’appelle elle-même pour résoudre un problème. Elle repose sur des relations de récurrence et agit comme une boucle implicite.
Pourquoi utiliser la récursivité ?
- Permet de résoudre des problèmes naturellement récursifs (ex. : suites, arbres).
- Offre une écriture plus intuitive et élégante.
- Peut être plus efficace pour certains algorithmes (ex. : parcours d’arbres).
- Remplace parfois les boucles pour des tâches répétitives.
- Tout algorithme récursif peut être transformé en version itérative.
2. Composantes d’une Fonction Récursive
Une fonction récursive comporte toujours :
- Une condition d’arrêt (cas de base) pour éviter une boucle infinie.
- Un appel récursif qui ramène le problème à une version plus simple.
Forme générale :
1
2
f(x) = si c(x) alors g(x) // condition d'arrêt
sinon h(f(s(x)), x) // appel récursif
Avec :
c(x)
: condition d’arrêt.g(x)
: cas trivial retournant une valeur constante.s(x)
: fonction successeur de x.h(f(s(x)),x)
: appel récursif.
Types de récursivité :
- Simple : Un seul appel récursif dans la fonction.
- Multiple : Plusieurs appels récursifs (ex. : Fibonacci).
- Terminale : L’appel récursif est la dernière instruction (optimisable).
- Non Terminale : L’appel récursif est suivi d’une opération.
- Croisée : Deux fonctions s’appellent mutuellement.
3. Exemples de Fonctions Récursives
3.1 Factorielle d’un Nombre (Récursivité Non Terminale)
La factorielle suit la relation : $N! = N × (N-1)!$ avec $1! = 1$.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int factorielle(int n) {
if (n == 1) {
return 1; // Cas de base
}
return n * factorielle(n - 1); // Récursivité
}
int main() {
int nombre = 5;
printf("Factorielle de %d = %d\n", nombre, factorielle(nombre));
return 0;
}
3.2 Factorielle en Récursivité Terminale
La version terminale évite de stocker des appels récursifs dans la pile.
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int factorielleRT(int n, int acc) {
if (n == 0) return acc;
return factorielleRT(n - 1, acc * n);
}
int main() {
int nombre = 5;
printf("Factorielle de %d = %d\n", nombre, factorielleRT(nombre, 1));
return 0;
}
3.3 Suite de Fibonacci (Récursivité Multiple)
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int fibonacci(int n) {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2); // Appels multiples
}
int main() {
int nombre = 6;
printf("Fibonacci(%d) = %d\n", nombre, fibonacci(nombre));
return 0;
}
4. Arbres de Récursivité
Un arbre de récursivité permet de visualiser l’enchaînement des appels récursifs d’une fonction.
Exemple : factorielle(5)
1
2
3
4
5
6
factorielle(5)
└── 5 * factorielle(4)
└── 4 * factorielle(3)
└── 3 * factorielle(2)
└── 2 * factorielle(1)
└── 1 (cas de base)
Chaque nœud représente un appel de la fonction. Lorsque le cas de base est atteint, les résultats sont remontés pour produire la réponse finale.
5. Erreurs courantes
- Oublier le cas de base → Boucle infinie entraînant un dépassement de pile.
- Récursivité non optimisée → Complexité exponentielle dans certains cas.
- Stack Overflow → Trop d’appels récursifs profonds sans optimisation.
- Utiliser une récursivité inefficace → Peut ralentir le programme (ex. : Fibonacci naïf).
6. Bonnes Pratiques
- Toujours définir un cas de base clair.
- Utiliser la récursivité terminale quand c’est possible.
- Optimiser avec la mémorisation (memoization) pour éviter les recalculs inutiles.
- Vérifier la profondeur de récursion pour éviter les erreurs de dépassement de pile.
- Évaluer si une solution itérative est plus efficace.
Le contenu de cet article est la propriété exclusive de son auteur.