Professional Documents
Culture Documents
INTRODUCERE
Recurena este prezent n lucrrile de matematic destul de timpuriu, cel
mai cunoscut exemplu fiind numerele Fibonacci care formeaz o secven de
numere ntregi. Aceast secven respect o anumit regul recurent: fiecare
numr este suma precedentelor sale dou numere. Excepia de la aceast regul o
reprezint numerele de nceput ale secvenei (0 i 1):
0, 1, 1, 2, 3, 5, 8, 13, 21 34, 55, 89, 144,
1. RECURSIVITATEA N PROGRAMARE
1.1. Motivaia folosirii recursivitii
Idea subprogramului (procedur sau funcie) care apeleaz un alt
subprogram este deja obinuit n limbajele de programare. Majoritatea
paradigmelor de dezvoltare a softului includ rafinarea problemei n subprobleme
pn cnd acestea din urm se pot concretiza n module, proceduri sau funcii.
Apoi apelul acestor module, proceduri sau funcii se face n mod natural n
procesul rezolvrii problemei iniiale. Deci mecanismul apelrii de subprograme
este folosit n toate limbajele de programare moderne, la baza lui stnd conceptul
de stiv. Implementarea specificaiilor unui limbaj de programare se face de obicei
de compilatorul limbajului respectiv. Fr a intra n prea multe amnunte, stiva se
definete ca o lista liniar care are principiul LIFO (ultimul element intrat n stiv
este primul utilizat i apoi scos din stiv). n stiva folosit de compilator se depune
contextul apelului, n care pe lng parametri de apel, variabilele locale ale
subprogramului, etc. se depune i adresa de revenire. Dac se fac mai multe
apeluri n cascad, atunci se rein n stiv adresele de revenire. La terminrea
apelurilor se revine la fiecare adres din stiv n mod invers depunerii n stiv, etc.
Acest mecanism este ilustrat n cele ce urmeaz. Fie 3(trei) proceduri numite P1,
P2 i P3 i secvena de pseudocod de mai jos:
Procedura P1(...)
Instruciuni
Apel P2()
InstRevP1
Sfarit P1;
Procedura P2(...)
Instruci
Apel P3()
InstRevP2
Instruciuni
Sfarit P2;
Procedura P3(...)
Instruciuni
Sfarit P3;
Instruciuni
Prin InstRevP1 s-a notat instruciunea de revenire din P2, iar prin InstRevP2 sa notat instruciunea de revenire din P3.
La apelul procedurii P2 din P1, stiva are structura:
Parametrii lui P1
1
5
n
n
1 5
1 5
2
2
Fn folosind funciile
(1)
{determina a la puterea
{determina F(n)
{cele 2 constante din formula
{constantele
la
puterea
phi1LaN:=exp(n*ln(phi1));
puterea}
phi2LaN:=Putere(phi2,n);
}
{phi1>0
si
se
poate
calcula
{functiei Putere
}
FibN:=trunc((phi1LaN-phi2LaN)/sqrt(5));{formula (1)
}
end;
var i:integer;
begin
writeln;
for i:=0 to 10 do
end.
write(FibN(i),' ');
(double x,double y)
- calculeaz x y;
Varianta C/C++:
#include<iostream.h>
#include<math.h>
long FibN(int n)
// determina F(n)
{ float
phi1= (1+sqrt(5.0))/2, // cele 2 constante din formula (1)
phi2= (1-sqrt(5.0))/2,
phi1LaN, phi2LaN;
// constantele la puterea n
phi1LaN= pow(phi1,n);
phi2LaN= pow(phi2,n);
return (phi1LaN-phi2LaN)/sqrt(5.0);
// formula (1)
}
void main()
{ int i;
for (i=0;i<=10;i++)
cout<<FibN(i)<<" ";
}
Varianta C/C++:
#include<iostream.h>
long fibNRec (long n)
{ if (n<2) return n;
//se returneaz 0 sau 1
return fibNRec(n-1) + fibNRec(n-2); //apelul dublu recursiv
}
void main (void)
{ int i;
for (i=0;i<=10;i++)
cout <<" "<<fibNRec(i);
}
}
}
}
}
}
}
}
SfPentru
1
n * factorial (n 1)
factorial (n)
pentru
pentru
n0
n0
Varianta PASCAL:
Varianta C/C++:
long Factorial(int n)
{ if (n==0)
return 1;
return n*Factorial(n-1);
}
Vom demonstra c:
1
1 2n
bn= n 1 C n2n n 1
Funcia generatoare este un polinom de grad infinit, avnd drept coeficieni, chiar
termenii irului, bn.
Presupunem c un arbore binar cu n noduri are:
un nod drept rdcin
k
noduri n subarborele stng
n-k-1
noduri n subarborele drept
Figura urmtoare ilustreaz acest fapt:
1 1 4z
, soluia
2z
bun
1 1 4z
1
1
1
1 1 4 z 1 2
1 C1n 2 (4 z ) n C1n 2
(1) n 2 2 n 1 z n
2z
2z
2 z
n0
n0
1
1 2n
1 (2n)!
C n2n
=
n 1 n
n 1 n! n! n 1
1 2n
bn= n 1 C n2n n 1
Apelul intermediar recursiv i nu direct (ca i cele care le-am folosit pn acum) se
obine cnd apelul recursiv al unei proceduri P1 nu se face n definiia ei ci ntr-o
alt procedur P2 apelat n prealabil n P1. Apoi din P2 se apeleaz iar P1. Nu
vom exemplifica aceast modalitate, pentru ca o considerm prea dificil pentru
nvmntul preuniversitar.
1
n * factorial (n 1)
factorial (n)
pentru
pentru
n0
n0
Pentru a calcula factorial(n) trebuie s nmulim n cu factorial(n1), care e definit cu ajutorul factorial(n-2),..., pn cnd ajungem la
factorial(0), care e definit explicit avnd valoarea 1. Pentru o astfel de
definiie poate c e potrivit notaie expresia condiional introdus de McCarty
[1], noaie care folosete expresii condiionale de forma:
`
[b1:e1, b2:e2,..., bn-1:en-1, en]
Spre exemplu:
CMMDC(345,1920)=CMMDC(1920,345)=CMMDC(345,195)=CMMDC(195,150
)=
CMMDC(150,45)=CMMDC(45,15)=CMMDC(15,0)=15
Deci apelul recursiv a fost utilizat de 6 ori.
Dac pentru un argument particular x tim valoare lui J0 i J1 atunci putem defini:
J(n,x)=[(n=0):J(0,x), (n=1):J(1,x), ((2*(n-1)/x*J(n-1,x)J(n-2,x)]
ac ac(m - 1,1),
ac(m - 1, ac(m, n - 1)),
daca m 0
daca n 0
altfel
NrCifre(123)=
1+(1+NrCifre(1))=1+1+1=3.
1+
NrCifre(12)=
1
1 NrCifre (n / 10)
NrCifre (n)
0n9
n 10
10
Varianta C/C++:
long NrCifre(long n)
{ if (n>=0 && n<10)
}
return 1;
return 1 + NrCifre(n/10);
n
(n mod 10) SumaCifre ( n / 10)
SumaCifre (n)
0n9
n 10
10
Varianta C/C++:
long SumaCifre(long n)
{ if (n>=0 && n<10)
}
return n;
return n%10 + SumaCifre(n/10);
ProdusCifre(123)=
3*(2*ProdusCifre(1))=3*2*1=6.
3*
ProdusCifre(12)=
n
(n mod 10) * Pr odusCifre (n / 10)
Pr odusCifre ( n)
0n9
n 10
10 ;
Varianta C/C++:
long ProdusCifre(long n)
{ if (n>=0 && n<10)
return n;
return n%10 + ProdusCifre(n/10);
}
Oglinda(123)=3*102+(Oglinda(12))=300+(2*101
0n9
Oglinda (n)
(n mod 10) * 10
NrCifre ( n / 10)
Oglinda(n / 10)
n 10
10
Execuia programului:
dati n=15249
oglinditul=94251
15249 nu este palindrom
Varianta C/C++: Dm programul complet care verific dac un numr dat n este
palindrom sau nu.
#include <iostream.h>
#include <conio.h>
#include <math.h>
long NrCifre(long n)
{if (n>=0 && n<10)return 1;
return 1+NrCifre(n/10);
}
long Oglinda (long n)
{int aux;
if (n >=0 && n<10)
return n;
else
{aux= NrCifre(n / 10);
return ((n % 10)*pow(10,aux) + Oglinda(n / 10));
}
}
void main()
{long n;
clrscr();
cout<<"dati n=";cin>>n;
cout<<Oglinda(n)<<endl;
if (n==Oglinda(n))
cout<<n<<" este palindrom";
else cout<<n<<" nu este palindrom";
getch();
}
Execuia programului:
dati n=152251
oglinditul=152251
152251 este palindrom
Execuia programului:
dati n=15249
a cata cifra =4
cifra este:5
Varianta C/C++:
#include<iostream.h>
#include<conio.h>
Execuia programului:
dati n=15249
a cata cifra =3
cifra este:2
Varianta Pascal:
program EuclidImpartire;
uses fdelay,crt;
type Natural=1..MaxLongInt;
function Cmmdc (a,b:Natural): Natural;
Begin
if a mod b = 0 then Cmmdc:= b
else Cmmdc:= Cmmdc (b, a mod b)
end;
var x,y:Natural;
begin
clrscr;
write ('dati x,y=');
readln (x,y);
write ('Cmmdc(',x,',',y,')=',Cmmdc (x,y));
readkey
end.
Execuia programului:
dati x,y= 100 12
Cmmdc(100,12)=4
Varianta C/C++:
#include <iostream.h>
#include <conio.h>
long Cmmdc(long a, long b)
{ if (!(a % b)) return b;
else return Cmmdc(b, a % b);
}
void main(void)
{ long x,y;
clrscr();
cout << "dati un numar natural=";
cin >> x;
cout << "dati alt numar natural=";
cin >> y;
cout << "cmmdc(" << x << "," << y << ")=" << Cmmdc (x,y);
}
Execuia programului:
dati un numar natural=100
dati alt numar natural=12
cmmdc(100,12)=4
Varianta PASCAL:
program EuclidScadere;
uses crt;
var x,y:longint;
function Cmmdc (a,b:longint): longint;
Begin
if a = b then Cmmdc:= a
else begin
if a>b then Cmmdc:= Cmmdc (a-b,b)
else Cmmdc:= Cmmdc (a,b-a);
end
end;
begin
clrscr;
write ('dati x,y=');
readln(x,y);
write ('cmmdc(',x,',',y,')=',Cmmdc (x,y));
readkey
end.
Execuia programului:
dati x,y= 1000 12
cmmdc(1000,12)=4
Varianta C/C++:
#include <iostream.h>
#include <conio.h>
long Cmmdc(long a, long b)
{ if (a == b) return a;
if (a>b) return Cmmdc (a-b,b)
return Cmmdc (a,b-a);
}
void main(void)
{ long x,y;
clrscr();
cout << "dati un numar natural="; cin >> x;
cout << "dati alt numar natural="; cin >> y;
cout << "cmmdc(" << x << "," << y << ")=" << Cmmdc (x,y);
}
Execuia programului: