Documente Academic
Documente Profesional
Documente Cultură
Recursivitatea
n programare, recursivitatea se refer la proprietatea unei funcii de a se putea apela pe ea nsi.
Cu alte cuvinte, spunem c o funcie este recursiv dac ea se autoapeleaz. Ea se poate autoapela fie
direct, fie indirect prin apelul altor funcii.
La apelurile recursive ale unei funcii aceasta este apelat nainte de a reveni din ea. La fiecare
reapel al funciei, parametrii i variabilele ei se aloc pe stiv ntr-o zon independent. De aceea, aceste
date au valori distincte la fiecare reapelare. Nu acelai lucru se ntmpl cu variabilele statice. Ele ocup
tot timpul aceeai zon de memorie i deci ele pstreaz valoarea la reapel.
Orice apel al unei funcii conduce la o revenire din funcia respectiv la punctul urmtor celui din
care s-a realizat apelul. Atunci cnd se revine dintr-o funcie se procedeaz la curirea stivei, adic stiva
se reface la starea ei dinaintea apelului. De aceea, orice apel al unui apel recursiv va conduce i la
curirea stivei, la o revenire din funcie, i deci parametrii i variabilele locale vor reveni la valorile lor
dinaintea reapelului respectiv. Numai variabilele statice rmn neafectate la o astfel de revenire.
Procesele recursive sunt strns legate de procesele iterative. Secvena iterativ presupune
execuia repetat a unei secvene de instruciuni, pn la ndeplinirea unei condiii (while, do-while, sau
for din C). Recursivitatea se refer la executarea repetat a unei secvene de instruciuni, ns pe parcursul
execuiei (nu la sfrit, ca n cazul iteraiei), se va verifica o condiie a crei valoare de neadevr implic
reluarea execuiei secvenei de instruciuni de la nceput, fr ca execuia curent s se fi terminat. n
momentul ndeplinirii condiiei, se va reveni n ordine invers din secvena de apeluri, relundu-se i
finalizndu-se apelurile suspendate.
Funciile recursive se utilizeaz la definirea proceselor recursive de calcul. Un proces de calcul
se spune c este recursiv, dac el are o parte care se definete prin el nsui. Un exemplu simplu de astfel
de funcie este funcia de calcul al factorialului, care se poate defini astfel:
factorial(n)=1, dac n=0, altfel
factorial(n)=n* factorial(n-1)
Alternativa:
factorial(n)=n* factorial(n-1)
Un proces recursiv trebuie mereu s conin o parte care nu se definete prin el nsui. n exemplul
de mai sus, alternativa:
factorial(n)=1, dac n=0
{
if (n==0)
return 1.0;
else
return n*factorial(n-1);
}
S urmrim execuia acestei funcii pentru n=3. La apelul din funcia principal se construiete o
zon pe stiv n care se pstreaz adresa de revenire n funcia principal, dup apel, precum i valoarea
lui n, aa cum este prezentat n figura de mai jos:
rev
adr1
figura 1
care autoapeleaz (direct) funcia factorial. Reapelarea funciei se realizeaz cu valoarea n-1=3-1=2.
prin aceasta se construiete o zon nou pe stiv, care conine revenirea la evaluarea expresiei de mai
sus, precum i valoarea nou a parametrului n, adic valoarea 2. Se obine starea din figura de mai jos:
rev
adr2
rev
adr1
figura 2
La o nou reapelare a funciei factorial, n=2>0, deci din nou se execut alternativa else. Evaluarea
expresiei conduce la o reapelare cu valoarea n-1=2-1=1. Se obine urmtoarea configuraie a stivei:
rev
adr3
rev
adr2
rev
adr1
figura 3
adr2
rev
adr2
rev
adr2
rev
adr1
figura 4
n acest moment n=0, deci se revine din funcie cu valoarea 1. Se cur stiva i se revine la
configuraia din figura 3. Adresa de revenire permite continuarea evalurii expresiei n*factorial(n-1). n
acest moment n are valoarea 1 i cum s-a revenit tot cu valoarea 1, se realizeaz produsul:
1*1=1
Dup evaluarea expresiei n*factorial(n-1) se realizeaz o nou revenire tot cu valoarea 1. Dup
curirea stivei se ajunge la configuraia din figura 2. n acest moment n are valoarea 2. Evalund expresia
n*factorial(n-1) se realizeaz produsul:
2*1=2
Apoi se revine din nou la funcia cu valoarea 2. Dup curirea stivei se ajunge la configuraia
din prima figur. n acest moment n are valoare 3. Se evalueaz expresia n*factorial(n-1) i se obine:
3*2=6
Se revine din funcie cu valoarea 6 (3!) i conform adresei de revenire, se revine n funcia
principal din care s-a apelat funcia factorial.
Programul care calculeaz factorialul unui ntreg preluat de la tastatur este prezentat n
continuare.
Ex. S se realizeze un program care calculeaz factorialul unui ntreg preluat de la tastatur.
#include <stdio.h>
main()
{
int n;
printf("Introduceti intregul pentru care se va calcula factorialul:");
scanf ("%d",&n);
printf("fact(%d)=%d",n,factorial(n));
}
factorial(int n)
{
if(n==0)
return 1;
else
return n*factorial(n-1);
}
Referitor la funciile recursive, trebuie specificat faptul c recursivitatea constituie un nou tip de
mecanism de control al programului. Din acest motiv, fiecare funcie recursiv va avea o instruciune if
care controleaz dac funcia se va apela pe ea nsi din nou sau dac va reveni n programul apelant.
Fr o astfel de instruciune, o funcie recursiv va rula necontrolat, folosind toat memoria alocat
stivei, conducnd n final la o blocare a calculatorului.
Recursivitatea poate fi util n simplificarea anumitor algoritmi. Spre exemplu, algoritmul de
sortare Quicksort este foarte dificil de implementat dac nu se folosete recursivitatea.
Ex. S se realizeze un program care afieaz descresctor (sau cresctor) numerele de la n la 0 (sau
0 la n) folosind o funcie recursiv, unde n este un ntreg introdus de utilizator.
#include <stdio.h>
main()
{
int n;
printf("Introduceti n>");
scanf("%d",&n);
afisare(n);
}
afisare(int n)
{
if (n>=0)
{
printf("%d ",n);
afisare(n-1);
}
}
28
12
12
4
dac b=0
afieaz cmmdc=a
altfel
calculeaz cmmdc (b, a%b)
2. Metoda scderilor succesive:
dac a=b cmmdc = a
dac a>b se calculeaz cmmdc (a-b,b)
dac b>a se calculeaz cmmdc (a,b-a)
4
0
a=
b=
28
12
16 (28 - 12)
12
4 (16 - 12)
12
dac a=b
afieaz cmmdc=a
altfel
dac a>b
calculeaz cmmdc (a-b, b)
altfel
calculeaz cmmdc (a, b-a)
4
8 (12 - 4)
4
4 (8 - 4)