Récursivité Définition récursive dun problème. Critère darrêt et convergence. Performance des...
-
Upload
simon-guegan -
Category
Documents
-
view
104 -
download
1
Transcript of Récursivité Définition récursive dun problème. Critère darrêt et convergence. Performance des...
Récursivité
Définition récursive d’un problème. Critère d’arrêt et convergence. Performance des algorithmes récursifs. Résolution d’un problème à l’aide de la récursivité.
2
Récursivité
Bourgeois gentilhomme (Acte II Scène IV) de Molière
Le héros, Monsieur Jourdain, veut connaître toutes les manières « galantes »d'écrire un billet.
De la phrase Belle Marquise, vos beaux yeux, me font mourir d'amour,il pourrait tirer
Vos beaux yeux, belle Marquise, d'amour me font mourir, puisVos beaux yeux, me font mourir, belle Marquise, d'amour, puisVos beaux yeux, me font mourir d'amour, belle Marquise etc.
Comment Monsieur Jourdain devrait-il procéder pour engendrer toutes cespermutations?
Le mieux pour lui pour être sûr d'y arriver est d'utiliser un procédé récursif.
On construit toutes les permutations de la phrasevos beaux yeux -- me font mourir -- d'amour; puis, dans ces permutations,on insère en première, deuxième, troisième et quatrième positionle morceau de phrase belle Marquise.
3
Récursivité : générateur de courbes fractales
générateur forme initiale arbre fractale
4
Récursivité
Une fonction ou une procédure récursive s’appelle elle-même.
Exemple I : Calcul de n!
#include <iostream.h>#include <cassert>
int Factorielle(int n)// Calcule la factorielle de n.//// Paramètre d'entrée :// n : un entier positif ou nul.//// Valeur de renvoi.// la valeur de n!{
assert(n >= 0);if (n == 0 || n == 1) return 1;return n * Factorielle(n - 1);
}
5
Récursivité
void main(){
int n;cout << "Entrez un nombre entier positif ou nul : ";cin >> n;cout << "La factorielle de " << n << " est : " << Factorielle(n) << endl;
}
Exemple II : Calcul du nième nombre de Fibonacci (Fn).
Fn =1 si n = 1 ou 2,
Fn-1 + Fn-2 si n > 2.
6
Récursivité
#include <iostream.h>#include <cassert>int Fibonacci(int n)// Calcule le n ième nombre de Fibonacci.//// Paramètre d'entrée :// n : un entier positif.// Valeur de renvoi.// la valeur du n ième nombre de Fibonacci.{
assert(n > 0);if (n == 1 || n == 2) return 1;return Fibonacci(n - 1) + Fibonacci(n - 2);
}void main(){
int n;cout << "Entrez un nombre entier positif : ";cin >> n;cout << "Le " << n << " ieme nombre de Fibonacci est : "
<< Fibonacci(n) << endl;}
7
Efficacité
Dans ces exemples, les fonctions récursives ne sont pas efficaces.
int Fibonacci(int n){
assert(n > 0);int F1 = 1;int F2 = 1;int resultat;
if (n == 1 || n == 2) return 1;for (int i = 3; i <= n; i++){
resultat = F1 + F2;F1 = F2;F2 = resultat;
}return resultat;
}
Évite de recalculerplusieurs fois
le même nombre.
Les appels récursifssont coûteux.
n = 50
Je n’ai pas réussi àobtenir une réponseavec l’approche récursive.
n = 47 Mauvais résultat
8
Efficacité
Fibonacci(5)
Fibonacci(4) Fibonacci(3)
Fibonacci(3) Fibonacci(2)
Fibonacci(2) Fibonacci(1)
Fibonacci(2) Fibonacci(1)
Beaucoup de redondance.
9
Coûteux en espace mémoire
Les fonctions récursives exigent aussi beaucoup d’espaces mémoires.
int Essai(int n)// Calcule la sommation suivante : 1 + 2 + ... + n.//// Paramètre d'entrée :// n : un entier positif.//// Valeur de renvoi.// la valeur de la sommation.{
assert(n > 0);int i;
if (n == 1) return 1;i = n + Essai(n - 1);return i;
}
10
Coûteux en espace mémoire
Essai(4)
n i
4 ?
3 ?Essai(3)
2 ?Essai(2)
1 ?Essai(1)
pile
Appels successifs Retours d’appels
Essai(4) 4 ?
3 ?Essai(3)
2 3Essai(2)
pile
Essai(4) 4 ?
3 6Essai(3)
Essai(4) 4 10
11
Usage d’une pile
#include <iostream.h>
void Lecture(){
char ch;
cin >> ch;if (ch != '#'){
Lecture();cout << ch;
}}
void main(){
Lecture();cout << endl;
}
abc#
cba
Affichage d’une chaîne inversée.
12
Stratégie pour résoudre un problème
La récursivité peut être utile pour résoudre un problème pouvant êtredécomposé en sous-problèmes de même type mais de plus petite taille.
3 étapes :
Décomposez le problème original en sous-problèmes ouenvisagez différentes façons pour simplifier les entrées.
Combinaison des solutions des sous-problèmes pour obtenirla solution du problème original.
Identification d’un cas trivial et de sa solution(sans appel récursif).
13
Exemple : la tour de Hanoï
Énoncé :
n disques de diamètres différents sont posés les uns sur les autres, par ordrede taille décroissante, sur un socle A,
il s’agit de les transférer sur le socle B en utilisant le socle C.
Déplacements autorisés : prendre un disque au sommet d’une des piles,le poser sur un disque plus grand ou
sur un socle vide.
État initialA B C
14
Exemple : la tour de Hanoï
Stratégie :
Transférer n – 1 disques de A à C en utilisant B comme socleintermédiaire.
Déplacer le disque qui reste en A sur B.
Transférer les n – 1 disques de C en B en utilisant A commesocle intermédiaire.
Cas trivial : si n est égale à 1 alors déplacer le disque de A dans B.
Cas général :
On dit que le jeu des Tours de Hanoï a pour origine unrituel des prêtres de Brahman pour prédire la fin du monde.Les prêtres de Brahman utilisaient n = 64 disques.
15
Exemple : la tour de Hanoï
#include <iostream.h>
void Hanoi(int n, char A, char B, char C){
if (n == 1) cout << "Deplacer le disque " << A<< " dans " << B << ".\n";
else{
Hanoi(n - 1, A, C, B);cout << "Deplacer un disque " << A
<< " dans " << B << ".\n";Hanoi(n - 1, C, B, A);
}}void main(){
Hanoi(5, 'A', 'B', 'C');cout << endl;
}
16
Algorithme d’Euclide : PGCD de 2 entiers
PGCD(m, n) =
PGCD(n, m) si n > m
m si n ≤ m, n = 0
PGCD(n, m % n) si n ≤ m, n > 0
#include <iostream.h>#include <cassert>int PGCD( int m, int n){
assert(m != 0 || n != 0);if(n != 0) return PGCD(n, m % n);return m;
}void main(){
int m, n;cin >> m >> n;cout << PGCD(m, n);cout << endl;
}
17
Comment déterminer si une chaîne est un palindrome ?
Une chaîne égale à elle-même en inversant tous ses caractères. Ex. : rotor
#include <iostream.h>#include <string.h>bool est_palindrome(char * s){
int i = strlen(s);if(i <= 1) return true;if(s[0] != s[i-1]) return false;char * raccourci = new char[i-1];strncpy(raccourci, s+1, i-2);raccourci[i-2] = '\0';return est_palindrome(raccourci);
}void main(){
char * chaine = "rotor";cout << est_palindrome(chaine) << endl;
}
18
Comment déterminer si une chaîne est un palindrome ?
Approche plus élégante.
#include <iostream.h>#include <string.h>bool souschaine_est_palindrome(char * s, int debut, int fin){
if (debut >= fin) return true;if(s[debut] == s[fin])
return souschaine_est_palindrome(s, debut+1, fin-1);else return false;
}bool est_palindrome(char * s){
return souschaine_est_palindrome(s, 0, strlen(s) - 1);}void main(){
char * chaine = "rotor";cout << est_palindrome(chaine) << endl;
}