Documente Academic
Documente Profesional
Documente Cultură
Recursivitatea este proprietatea unei entiti (algoritm, program, structur de date, figur etc.) de a putea fi descris prin entiti de acelasi tip cu ea nsi. Recursivitatea
este larg folosit n matematic i este, tot o dat, o tehnic important de elaborare a algoritmilor. Vom arata, de asemenea, c i unele structuri de date au caracter recursiv, ceeace faciliteaz
anumit proprietate P este valabil pentru toate elementele unui ir de entiti E1, E2, E3, ... Ek, Ek+1, .... Raionamentul conine doua etape: se stabilete c proprietatea P are
1.
loc pentru elementul E1 (eventual pentru un numr finit de elemente E1, E2, ..., Em); 2. se demonstreaz c, dac proprietatea P are loc pentru un element oarecare Ek, ea are loc i pentru elementul
Funcia recursiv este o funcie n corpul creia exist apeluri la ea nsi. n mod similar, o procedur n
corpul creia exist apeluri la ea nsi este recursiv. n programarea orientat pe obiecte, funciile i procedurile se realizeaz sub form de metode. n consecin, funciile i
pentru k>0 2. Funcia lui Fibonacci: fib(0)=fib(1)=1 fib(k)=fib(k1)+fib(k-2) pentru k>1 3. Funcia lui Ackerman Este un exemplu de funcie care
creste mai rapid decat cea exponenial i se definete astfel: Fie m i n numere naturale; ack(0, n) = n+1; ack(m, 0) = ack(m-1, 1) pentru m>0; ack(m, n) =
ack(m-1, ack(m, n1)) pentru m>0 si n>0. Remarcm c, n ultima linie a acestei definiii, are loc o dubl invocare recursiva a funciei: o dat pentru calcularea celui de al doilea argument i nc o
Din exemplele de mai sus, constatm urmatoarele: n definiia unei funcii recursive trebuie sa fie obligatoriu
prevzute i condiii de terminare n care valoarea ntoars este calculat direct, fr a mai recurge la invocarea recursiv a aceleeai funcii;
algoritmul trebuie sa fie astfel conceput, nct dup efectuarea unui numar finit de apeluri recursive s fie satisfcute condiiile de terminare.
Exist i posibilitatea ca
recursia sa fie indirect: n corpul funciei f este invocat funcia g, iar n corpul funciei g este invocat funcia f. Cercul acestor invocri succesive poate sa conin mai mult de dou
funcii.
Procedurile nu au valoare ntoars, ci numai efect lateral. n consecin, folosirea procedurilor recursive se bazeaz pe cumularea efectelor laterale,
care const n modificarea valorilor unor variabile globale sau valorilor parametrilor procedurii. n limbajul Java nu exist variabile globale, dar pot fi modificate valorile unor cmpuri ale
clasei creia i aparine metoda recursiv sau ale unor componente ale obiectelor primite ca parametri.
Comparaie ntre iteraie i recursie
iterativ, ct i prin unul recursiv. Uneori ns, iteraia este mult mai rapid dect recursia i consum mai puin memorie. n schimb, utilizarea funciilor sau procedurilor recursive este mai
elegant i face algoritmul mai uor de neles i de verificat. n plus, folosirea recursivitii este o tehnic foarte eficient de concepere a algoritmilor. Din aceasta cauz, muli algoritmi
sunt concepui mai nti n varianta lor recursiv i apoi, numai dac aceasta variant necesit timp de calcul sau memorie prea mare, se caut i o variant iterativ.
De foarte multe ori,
trecerea de la varianta recursiv la cea iterativ a algoritmului se face nlocuind funcia recursiv printr-un ciclu. De exemplu, pentru calcularea factorialului, se poate folosi fie funcia recursiv
static long factorial(long n) throws Exception {
return f; }
Complexitatea
ambelor funcii este liniar O(n). Vom arta totui, c exist i situaii n care nlocuirea recursiei prin iteraie necesit folosirea unei structuri de stiv. Exemplu n fisierul Fibonacci.jav
a se d un exemplu de aplicaie n care se testeaz doua variante de calcul al funciei Fibonacci: varianta recursiv, care respect definiia dat mai sus, i varianta iterativ. Argumentul funciei se d ca argument
n linia de comand. Pentru fiecare din aceste variante se determin i timpul de calcul (n milisecunde). n acest scop, nainte i dup invocarea metodei respective se invoc metoda , care intoarce timpul
System.currentTimeMillis()
indicat de ceasul sistemului, i se face diferena, obinnd timpul de calcul n milisecunde. Este posibil ca, pentru valori mici ale argumentului funciei, durata de calcul n ambele variante s fie 0 (adic mai mic de o
milisecund). Se constat ns c la valori mai mari ale argumentului (peste 25) diferena dintre cele doua variante devine din ce n ce mai mare, n defavoarea celei recursive. Memoria ocupat este, de asemenea, mult mai
mare la varianta recursiv, unde se pun pe stiva sistemului toate datele de la invocrile intermediare ale funciei, n timp ce n varianta iterativ este necesar s se memoreze de la o iteraie la alta numai
doua valori: i . Explicaia este c cei doi algoritmi folosii pentru calculul funciei Fibonacci au complexiti diferite. n varianta iterativ exist un singur ciclu, care se parcurge de n-2 ori,
f1=fib(i1) f2=fib(i-2)
deci algoritmul are complexitate liniar O(n). n varianta recursiv, numarul de apeluri recursive ale funciei fibonacci(k) se obine ca suma unei progresii geometrice cu raia 2 i deci este de n ordinul 2 . ntr-
adevar, pentru calcularea lui fibonacci(n) este necesar sa se calculeze fibonacci( n-1) si fibonacci(n2). Pentru calcularea fiecreia din aceste valori sunt necesare alte dou apeluri ale funciei fibonacci i aa mai departe,
pn se ajunge la fibonacci(1). Complexitatea algoritmului recursiv este deci, n acest caz, n exponential O(2 ).