Introduction à la récursivité Structures de données Introduction à la récursivité 2005/2006
Raisonnement par récurrence (Math) Récursivité Raisonnement par récurrence (Math) Exemple : Montrer que : Preuve : Cas de base : n = 0 : (Vrai) n = 1 : (Vrai) Récurrence : Hypothèse : S(n) est vrai, n>1 montrer que S(n+1) est vrai
Récursivité å hypothèse de récurrence ) 1 ( n S i + = ) ( 2 )( 1 i = hypothèse de récurrence ) ( 2 )( 1 vrai n + =
Équations de récurrence Récursivité Équations de récurrence Base : S(0) = 0 Récurrence : S(n+1) = S(n)+(n+1) La récursivité est un mécanisme de calcul puissant Résoudre un problème de taille n peut se ramener à la résolution d’un (plusieurs) sous problème(s) de taille plus réduite ...
Récursivité Action récursive Action calculer S(n) : S(3) ? une action A est exprimée de façon récursive si la décomposition de A fait appel à A (une procédure/fonction qui s’appelle elle-même est dite récursive) Action calculer S(n) : Appliquer les deux règles suivantes: 1) S(0) = 0 (règle de base) 2) S(n) = S(n-1) + n , n>0 (règle de récurrence) S(3) ? = S(2) +3 = (S(1)+2 ) +3 = ((S(0)+1)+2)+3 = ((0+1)+2)+3 = 6
Récursivité Objet récursif La définition d’un objet est récursive lorsqu’elle se formule en utilisant l’objet même qu’elle entend définir Exemple (déf. récursive d’une chaîne) Une chaîne de caractères est : soit la chaîne vide soit un caractère suivi d’une chaîne de caractères
La récursivité est un Récursivité Exemple (suite) D’après la définition précédente : "a" est une chaîne : un caractère ‘a’ suivi d’une chaîne vide "ab" est une chaîne : un caractère ‘a’ suivi de la chaîne "b" La récursivité est un mécanisme puissant de définition d’objets
Récursivité vs Itération procédure Itération( ) tantque (condition) faire <Instructions> fin tantque procédure Itération( ) si (condition) alors <Instructions> Itération() finsi fonction S(n) : entier s 0 tant que (n>0) faire s s+n n n-1 fin tant que retourner s fonction S(n) : entier Si (n=0) alors retourner 0 sinon retourner S(n-1)+n fin si
Récursivité : applications Exemple 1 : calcul de la factorielle Équations de récurrence : 0! = 1 (base) n! = n*(n-1)! (récurrence) fonction fact(d n:entier): entier si n = 0 alors retourner 1 sinon retourner n * fact(n-1) fin si fin action Que se passe-t-il si n <0? récursivité infinie
Récursivité : applications La fonction factorielle en Java int fact(int n) //doit être déclarée dans une classe //précondition : n0 { if (n==0) return 1; else return n * fact(n-1); }
Récursivité : applications La fonction factorielle : exécution fact(4) if(4==0) return 1; else return 4*fact(3); if(3==0) return 1; else return 3*fact(2); if(2==0) return 1; else return 2 * fact(1); if(1==0) return 1; else return 1 * fact(0);
Récursivité : applications La fonction factorielle : exécution (suite) fact(4) if(4==0) return 1; else return 4*6; if(3==0) return 1; else return 3 * 2; 24 6 2 if(2==0) return 1; else return 2 * 1; if(1==0) return 1; else return 1 * fact(0); 1
Récursivité : applications Exemple 2 : suite de fibonacci Équations de récurrence : u(0) = 0, u(1) = 1 (Base) u(n) = u(n-1)+u(n-2), n>1 (récurrence) fonction u(d n:entier) : entier si (n=0) ou (n=1) alors retourner n sinon retourner u(n-1) + u(n-2) fin si fin action
Récursivité : applications suite de Fibonacci en Java int fib(int n) //doit être déclarée dans une classe //précondition : n0 { if (n<2) return n; else return fib(n-1) + fib(n-2); }
Récursivité : applications suite de Fibonacci : exécution fib(4) ? Résultat = 3 fib(4) 2 3 2 1 + fib(2) fib(3) 1 + 2 1 + 1 1 fib(2) fib(1) fib(1) fib(0) 1 + 1 appel : retour : fib(1) fib(0)
Récursivité : applications Suite de Fibonacci (suite) O(2n-1) appels à la fonction fib pour n = 100 , O(299) O(1030) !!! Une solution récursive n’est pas toujours viable solution itérative
Récursivité : applications Suite de fibonacci : solution itérative int fib(int n) { int x, y, z, i; if(n<2) return n; else { x = 0; // u(0) y= 1; // u(1) for(i=2;i<=n; i++) { z = x+y; // u(n) = u(n-1)+u(n-2) x = y; y = z; } return z;
Récursivité : applications Les Tours de Hanoï (TH) 3 axes, n disques concentriques de taille différente But : déplacer tous les disques de G à D Règles : 1 seul disque peut être déplacé à la fois 1 disque ne peut jamais être déposé sur un plus petit 1 disque ne peut être déposé que sur G, M ou D G(auche) n M(ilieu) D(roite)
Récursivité : applications TH : idée de la solution récursive exprimer le problème des n disques à l’aide de la même solution sur n-1 disques (base) savoir résoudre le problème pour 1 disque Équations de récurrence G(auche) M(ilieu) D(roite) (n=1)
Récursivité : applications 1 3 2 G(auche) M(ilieu) D(roite) (n=2) (n=3) …, bonne chance Récurrence : Hypothèse: on connaît la solution pour n disques Trouver la solution pour n+1 disques
Récursivité: applications 3(hypo) 1(hypo) n+1 2 G(auche) M(ilieu) D(roite) Solution procédure déplacer(n, G, M, D) " déplacer n disques de G vers D en utilisant l’axe M " (Base) n=1, déplacer un disque de G vers D (récurrence) déplacer(n-1, G, D, M) déplacer un disque de G vers D déplacer(n-1, M, G, D)
Récursivité : applications void deplacer(int n, char G, char M, char D) { if (n==1) //cas de base System.out.println( "déplacer le disque de " + G + " vers " + D ); else //récursivité deplacer(n-1, G, D, M); deplacer(1, G, M, D); deplacer(n-1, M, G, D); } public static void main(String [] args) deplacer(4, ‘g’, ‘m’, ‘d’);
Récursivité : pile d’exécution(exemple) procédure P(d n : entier, r s : entier) variable c : entier début si (n = 0) alors s 0 sinon c n mod 10 P(n div 10, s) s s +c fin si fin Programme PP variable nb 37, sc : entier P(nb, sc); afficher ("somme des chiffres de", nb, "est ", sc) nb sc PP n s P c 3 37 7 0 3 10 Pile d’exécution
Récursivité mutuelle (croisée) Récursivité directe : une fonction s’appelle elle-même Récursivité indirecte : une fonction appelle d’autres fonctions qui appellent d’autres fonctions qui appellent la fonctions initiale Récursivité mutuelle : deux fonctions s’appellent mutuellement (c’est une forme de récursivité indirecte)
Récursivité mutuelle (croisée) Récursivité directe Récursivité indirecte Récursivité mutuelle f() h() g() f() f() g()
Récursivité terminale Un appel récursif est terminal si aucune instruction n'est exécutée après l'appel récursif. L'appel récursif est la dernière instruction exécutée Un algorithme en récursivité terminale est équivalent à une boucle tantque Exemple : void f(int i) { if(i>0) { System.out.println(i); f(i-1); }
Récursivité non terminale Quand l'appel récursif ne termine pas la fonction, on parle de récursivité non-terminale. Il y a des instructions à exécuter après l'appel récursif. La suppression de la récursivité non-terminale est plus difficile, il faut utiliser une pile. Exemple : void f(int i) { if(i>0) { f(i-1); System.out.println(i); }
Récursivité Conclusion La récursivité est un principe puissant nous permettant : de définir des structures de données complexes de simplifier les algorithmes opérants sur ces structures de données Pour certains problèmes, une solution itérative est préférable à une solution récursive Il est possible de transformer un algorithme récursif en un algorithme itératif. On dit "dérécursiver" l’algorithme