Académique Documents
Professionnel Documents
Culture Documents
Rcursivit
1.1 Introduction
La rcusivit permet de rsoudre certains problmes d'une manire trs rapide, alors que si on devrait les rsoudre de manire itrative, il nous faudrait beaucoup plus de temps et de structures de donnes intermdiaires.
1.2 Principe de la rcursivit
Une fonction rcursive est une fonction qui s'appelle elle mme.
1.2.1 Construction d'un algorithme rcursive
C'est un peu comme dnir une suite par rcurence en mathmatiques, il faudra : 1. Un ou plusieurs cas de base, dans lequel (lesquels) l'algorithme ne s'appelle pas lui mme, sinon l'algorithme ne peut pas terminer (s'arrter). 2. Si on ne se situe pas dans un cas de base (on parle de cas "inductif "), l'algorithme fait appel lui mme (appel rcursif). Chaque appel rcutrsif doit, en principe, se rapprocher d'un cas de base, de faon permettre la terminaison du programme.
Exemple 1 La factorielle On rappelle que la factorielle d'un nombre n est dnit comme suit : n! = 1 2 3... n. Les versions itrative :
int fact(int n) { if (n==0) return 1; else { int p=1; for (int i=1; i<n; i++) p=p*i ; return p; } }
La version rcursive :
int fact(int n) { if (n==0) return 1; else return (n*fact(n)) }
1
L'arbre d'excution :
L'environnement local
Un point essentiel, chaque appel rcursif dispose de ses propres variables locales. Ces variables sont dclares chaque appel (voir l'exemple ci-dessous), ceci est galement vrai pour les paramtres.
Les variables a et b sont dclares chaque appel. Ce qui donne comme arbre d'excution :
Figure 1.2 L'arbre d'excution de la fonction comb avec les variables a et b locales
L'environnement global
Si on veut partager une variable, il faut la dclarer en dehors de la fonction. Si on prend, par exemple, la fonction comb (de l'exemple prcdent), ce qui donne :
Figure 1.3 L'arbre d'excution de la fonction comb avec les variables a et b globales
1.2.3 Fonctionnement de la rcursivit
Dnition 1 Pile d'excution Une pile d'excution est la structure de donnes (en mode pile) qui mmorise l'ensemble des appels d'une fonction en retenant quelle partie du code source revenir une fois la fonction termine.
Lors de l'excution d'un programme, cette pile permet de : 1. mmoriser le contexte appelant lors de chaque appel de fonction (adresses des variables, l'adresse de la prochaine instruction, .. etc.). A ce niveau on fait appel la fonction empiler. 2. rstituer ce contexte au retour. A ce niveau on fait appel la fonction dpiler.
Exemple 4 Pile d'excution de la fonction fact Soit la fonction rcursive "fact" dnie prcdemment. On donne ci-dessous la table d'excution suivie de la pile d'excution :
Num d'appel
Num Retour
Contexte
Action
N*fact(2) N*fact(1) N*fact(0) Return(1) Return(1*1) Return(2*1) Return(3*2) Retour au point appelant
L'inconvnient majeur des algorithmes rcursifs est le problme d'encombrement mmoire. Par consquent, on essaie de diminuer la taille de la pile d'excution en utilisant des algorithmes itratifs. Pour crire un algorithme quivalent, on doit grer dans l'algorithme la pile des sauvegardes (ne garder que celles utiles). Autrement dit : Transformer un algorithme rcursif en une version itrative quivalente qui conduise une diminution de la pile.
1.3.1 Un seul appel rcursif terminal
Dnition 2 fonction rcursive terminale Un algorithme est dit rcursif terminal si aucun traitement n'est eectu la remonte d'un appel rcursif (sauf le retour de la valeur).
Dans le cas o la fonction rcursive la structure suivante :
Dnition 3 fonction rcursive non terminale Un algorithme est dit rcursif non terminal si un traitement est eectu la remonte d'un appel rcursif.
Dans le cas o la fonction rcursive la structure suivante :
T1 fonct(T2 x){ if (c(x)) return f(x); else { p=g(x); x=h(x); while(!c(x)) { p=u(p,g(x)); x=h(x) fonct(F1(x)); } return u(p,f(x)); } }
}
1.4
1.4.1
} return p*n;
Exemples d'application
Calcul du PGCD
PGCD(p, q) = si p = 0 alors q sinon si q = 0 alors p sinon si q = p alors PGCD(p-q, q) sinon PGCD(p, q-p)
Donnez la fonction rcursive PGCD. Pour donner la fonction rcursive, en premier lieu, on essaie de donner l'criture mathmatique, ce qui donne :
si p = 0 si q = 0 si q p si q > p
int PGCD(int p, int q) { if (p == 0) return q; else if (q == 0) return p; else if (q <= p) return PGCD(p-q, q); else return PGCD(p, q-p); }
1.4.2 La suite de Fibonacci
Fibo(1)=Fibo(2)=1, Fibo(n+2)=Fibo(n+1)+Fibo(n).
Pour donner la fonction rcursive, en premier lieu, on essaie de donner l'criture mathmatique, ce qui donne :