Sunteți pe pagina 1din 8

Recursivitate

Un algoritm se numete recursiv dac se autoapeleaz adic, dac n corpul su exist un modul care se
autoapelez.
Recursivitatea se realizeaz cu ajutorul subprogramelor. Un subprogram care se autoapeleaz se
numete subprogram recursiv.
Prin urmare un algortim se numete recursiv sau un program se numete recursiv dac conine cel puin un
subprogram care se autoapeleaz.
Recursivitatea este folosita cu multa eficienta in matematica. Spre exemplu, definitiile matematice
recursive sunt:

Definitia functiei factorial


fact:N->N
fact(n) =
1, daca n=0
n*fact(n-1), daca n>0
Definitia functiei Ackermann
ac:NxN->N
ac(m,n) = n+1, daca m=0
ac(m-1,1), daca n=0
ac(m-1,ac(m,n-1)), daca m,n>0
Definitia functiei Fibonacci
fib:N->N
fib(n)=
0, daca n=0
1, daca n=1
fib(n-2)+fib(n-1), daca n>1

Recursivitatea se realizeaz n felul urmtor:


Din afara subprogramului facem un apel al subprogramului
Dac nu este ndeplinit o condiie (numit condiie de oprire), algoritmul se autoapeleaz de un anumit
numr de ori (pn cnd e ndeplinit condiia).
La fiecare nou autoapelare a subprogramului se reexecut secvena de instruciuni din corpul su, eventual cu alte
date, crendu-se un lan de autoapeluri recursive.
Dac condiia de oprire nu este ndeplinit niciodat sau nu exist, algoritmul va avea un rezultat asemntor intrrii
ntr-un ciclu infinit.
Intuitiv, putem spune c un algoritm recursiv are acelai efect ca i o bucl (ciclu, instruciune repetitiv)
repet execia unui set de instruciuni. n mod analog, deducem c repetarea nu trebuie s se realizeze de un numr
infinit de ori. De aici provine necesitatea existenei condiiei de oprire.
Prin urmare orice subprogram recursiv trebuie s ndeplineasc urmtoarele condiii:

1. s se poat executa cel puin o dat fr a se autoapela (cnd apare condiia de oprire);
2. toate autoapelurile s se produc astfel nct la un moment dat s se ajung la ndeplinirea
condiiei de oprire.
Cea mai mare parte a algoritmilor repetitivi se pot implementa ntr-o variant nerecursiv (numit
variant iterativ) folosind instruciuni recursive, ct i ntr-o variant recursiv atunci cnd conin un modul definit
recursiv.
Varianta de implementare rmne la latitudinea programatorului.
Varianta recursiv este recomandat n cazul n care problemele sunt definite printr-o relaie de recuren ns
acest timp de algoritmi sunt mai greu de urmrit i de obicei necesit un timp de execuie mai mare.
n viaa de zi cu zi ne putem ntlni cu iruri de elemente definite recurent ca de exemplu:

1. irul numerelor naturale (primul numr este 0; celelalte se obin din precedentul adugnduse 1)
2. suma numerelor naturale (iniial suma este 0; fiecare element care trebuie adugat se adaug
la suma obinut din elementele aflate naintea lui)
3. irul lui Fibonacci
4. cmmdc dintre 2 numere
5. etc
De asemenea ne nlnim i cu alte elemente i fenomene care pot permite o reprezentare recursiv:

1.
succesiunea zilelor i nopilor
2.
o camer de luat vederi care este ndreptat spre o oglind. V propun s v
gndii ce se vede n camer.
Etc.
Dup cum am mai spus execuia subprogramelor recursive seamn cu execuia instruciunilor repetitive.
Diferea const n faptul c autoexecuia, n cazul programelor recursive, nu se poate realiza de un numr infinit de
ori deoarece la fiecare autoapel se pstreaz n stiva calculatorului variabilele locale i parametrii trimii prin valoare
iar stiva are o dimensiune limitat.
Reamintim c Stiva reprezint o succesiune ordonat de elemente, delimitat de dou capete, n care adugarea
i eliminarea elementelor se poate face pe la un singur capt, numit vrful stivei. Extragerea elementelor se
realizeaz n ordine invers introducerii lor.
n cazul unui subprogram recursiv (care este n acelai timp modul apelat i apelant) acest mecanism al stivei
este de o foarte mare importan: atunci cnd se execut un lan de autoapeluri recursive, la fiecare autoapel
variabilele locale i parametrii subprogramului recursiv se salveaz pe stiv, iar la revenirea aceste valori sunt
preluate din stiv n ordinea invers a introducerii lor.
Cum lucreaz un subprogram recursiv?
Presupunem c dorim s gsim valoarea celui de-al n-lea termen din irul lui Fibonacci. irul este definit n felul
urmtor:

F(0)=0, dac n=0


2

F(1)=1, dac n=1


F(n)=F(n-1)+F(n-2), dac n>=2.
Ne propunem s gsim ct este f(7), adic cel de-al aptelea termen din irul lui Fibonacci.
Apelm funcia cu parametru 7 dar observm c nu putem calcula dect dac tim valorile termenilor al aselea
i al cincelea. Termenul al aselea nu-l putem calcula dect dac tim valorile termenilor al cincelea i al patrulea
amd.
F(7)=F(6)+F(5)
F(6)=F(5)+F(4)
F(5)=F(4)+F(3)
F(4)=F(3)+F(2)
F(3)=F(2)+F(1)
F(2)=F(1)+F(0)
F(1)=1
F(0)=0
Ne ntoarcem prelund din stiv rezultatele salvate.
Vom calcula mai nti pe F(2) pentru c tim ct este F(1) i F(0). F(2)=1+0=1.
tiind ct este F(2) putem calcula pe F(3). F(3)=F(2)+F(1)=1+1=2.
Acum putem calcula i pe F(4)=F(3)+F(2)=2+1=3.
Avem toate elementele pentru a calcula i F(5)=F(4)+F(3)=3+2=5.
Ne ntoarcem i la F(6)=F(5)+F(4)=5+3=8.
Acum putem s aflm ct este al aptelea termen din irul lui Fibonacci: F(7)=F(6)+F(5)=8+5=13.
Dup cte se observ autoapeluri tind s se execute pn se ajunge la condiia de oprire (adic condiia n cazul
n care rezultatele sunt cunoscute, n cazul nostru pentru n=0 i pentru n=1) i apoi se preiau rezultatele intermediare
din stiva calculatorului n calculnd termenii intermediari.

**
//apel recursiv
int fact(int n)
{
if(n==1)
return 1;
return n*fact(n-1);
}

//varianta nerecursiva
int fact(int n)
{
int i,f;
for(i=f=1;i<=n;i++)
f*=i;
return f;

}
// Observatie: tipul functiei trebuie sa devina long pentru
// n>=8 ( 8!>32767 )
Se citeste n.Sa se calculeze termenul de ordin n al sirului lui Fibonacci in varianta recursiva
#include<iostream>
int n;
int f(int n)
{
if(n==0) return 0;
else if(n==1) return 1;
else return f(n-1)+f(n-2);
}
int main()
{

cout<<"n=";cin>>n;
cout<<"termenul de ordin "<<n<<" este: "<<f(n);
}

Exercitii:
** Sa se scrie o functie recursiva care calculeaza si returneaza suma cifrelor unui numar natural primit ca
parametru.
#include<iostream.h>
int sumacif(long n)
{ if(n==0) return 0;
else return sumacif(n/10)+n%10;
}
void main()
{
cout<<sumacif(23562);
}

**Sa se scrie o functie recursiva care sa afiseze descompunerea in factori primi a unui numar natural .
using namespace std;
#include<iostream>
void desc(int n, int d)
{ if(n>1)
if(n%d==0) { cout<<d<<" ";
desc(n/d,d);
}
else desc(n,d+1);
}
int main()
{
desc(28,2);
}
** Sa se scrie o functie recursiva care primeste un parametru n numar natural si afiseaza:
1
12
123
.....
1 2 3 4 ... n
#include<iostream>
using namespace std;
void afis(int n)
{ if(n>0)
{
afis(n-1);
for(int i=1;i<=n;i++) cout<<i<<" ";

#include<iostream>
using namespace std;
void afis(int n)
{ if(n>0)
{
for(int i=1;i<=n;i++) cout<<i<<" ";
cout<<endl;
afis(n-1);
}
}
int main()
{
afis(6);
return 0;
}

cout<<endl;
}
}
int main()
{
afis(6);
return 0;
}
**Sa se determine cifra maxima a unui numar natural folosind o functie recursiva.
#include<iostream>
using namespace std;
int max(int n)
{ if ( n <= 9 ) return n;
else
{
int m = max(n/10);
if ( m > n%10 )
return m;
else
return n%10;
}
}
int main()
{int n;
cout<<"te gandesti la un numar:"; cin>>n;
cout <<"cifra maxima este: "<< max(n);
return 0;
}
**Sa se scrie o functie recursiva care primeste ca parametru litera 'A' si afiseaza in ordine toate literele mari din
alfabet.
using namespace std;
#include<iostream>
void litere(char c)
{ if(c<='Z') { cout<<c<<" ";
litere(c+1);
}
}
int main()
{char c;
for(c='a'; c<='z';c++)
cout<<c<<" ";
cout<<endl;
litere('A');
}

**Sa se scrie o functie recursiva care primeste ca parametru un sir de caractere format din cel mult 100 de
caractere litere mici si elimina toate vocalele din sir.
#include <iostream>
#include<string.h>
using namespace std;
void elimin(char a[100])
{
if(strlen(a)>0)
if(strchr("aeiou",a[0]))
{ strcpy(a,a+1);
elimin(a);
}
else elimin(a+1);
}
int main()
{ char a[100]="abracadabra";
elimin(a);
cout<<a;
return 0;
}
**Sa se calculeze CMMDC al doua numele naturale folosind o functie recursiva.
#include<iostream>
using namespace std;
int cmmdc(int x, int y)
{ if(x%y==0) return y;
else return cmmdc(y,x%y);
}
int main()
{
cout<<cmmdc(55,45);
return 0;
}
#include<iostream.h>
void litere(char c)
{ if(c<='Z') { cout<<c<<" ";
litere(c+1);
}
}
void main()
{
litere('A');
}
6

** Sa se scrie o functie recursiva care primeste un parametru n numar natural si returneaza numarul obtinut din
n prin scaderea cu 1 a cifrelor impare si marirea cu 1 a celor pare.
Ex. din n=2324 returneaza 3235
using namespace std;
#include<iostream>
long schimba(long n)
{ if(n==0) return 0;
else if(n%2==1) return schimba(n/10)*10+n%10-1;
else return schimba(n/10)*10+n%10+1;
}
int main()
{
cout<<schimba(23362);
}

** Sa se scrie o functie recursiva care primeste un parametru n numar natural si returneaza numarul obtinut din
n prin eliminarea cifrelor pare.
Ex. din n=23524 returneaza 35
using namespace std;
#include<iostream>
long sterge(long n)
{ if(n==0) return 0;
else if(n%2==1) return sterge(n/10)*10+n%10;
else return sterge(n/10);
}
int main()
{
cout<<sterge(23562);
}
** Formulati un enunt:
#include<iostream>
using namespace std;
int n, a[100];
void citire(int a[100], int n)
{
if(n>0)
{ citire(a,n-1);
cin>>a[n];
}
}
int sumacif(int n)
{
if(n==0) return 0;
else return n%10+sumacif(n/10);
}
int suma(int a[100], int n)
7

{
if(n==0) return 0;
else return
suma(a,n-1)+sumacif(a[n]);
}
int main()
{
cin>>n;
citire(a,n);
cout<<suma(a,n);
return 0;
}

S-ar putea să vă placă și