Sunteți pe pagina 1din 52

RECURENTA VERSUS ITERATIE

Facultatea de Matematica si Informatica,


Universitatea din Bucuresti

7 aprilie 2012

1
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Noţiunea de algoritm = notiune primară.


Există descrieri şi proprietăţi:
Un algoritm constă dintr-o mulţime finită de paşi, fiecare necesitând
una sau mai multe operaţii.
Pentru a fi implementate pe un calculator, într-un anumit limbaj de
programare, aceste operaţii trebuie să fie:
 definite;
 efective.
Caracteristicile algoritmilor
 corectitudinea;
 finititudinea:;
 generalitatea;
 completitudinea;
 claritatea.

2
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Studiul algoritmilor cuprinde mai multe aspecte (1):


Elaborarea algoritmilor.
Tehnici de elaborare (reguli) + creativitate (intuiţie) = soluţie
Exprimarea algoritmilor

- scheme logice, limbaje de tip pseudocod, programe in diferite


limbaje de programare.
- se impune utilizarea unui anumit stil de programare (legat nu de un
anumit limbaj de programare, ci de tipul limbajului şi de modul de
abordare)

3
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Studiul algoritmilor cuprinde mai multe


aspecte (2):
 Validarea algoritmilor (demonstrarea
matematica a corectitudinii, independent de
implementare).
 Analiza algoritmilor. (in general: timpul de
calcul şi/sau la memoria necesară)
 Testarea programelor :

(i) depanarea (debugging) Cf. E.W.


Djikstra, prin depanare putem evidentia
prezenta erorilor dar nu si absenta lor!
(ii) verificare (profiling)

4
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Incercarea de definire (decada 1930-1940):


Sunt propuse diverse formalisme pentru
notiunea de algoritm:
 Functiile -calculabile (Alonzo CHURCH şi
Stephen Cole KLEENE);
 Masinile Turing (Alan TURING);

 Functiile general recursive (Kurt GÖDEL);

 Sistemele Post, inclusiv masina Post-Turing


(Emil Leon POST);
 Algoritmii normali Markov (N.N. MARKOV)

Toate teoriile: echivalente 


Teza Church-Turing (cele 2 variante)

5
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Lambda calculul
O λ-functie este definită de o lambda-expresie care
exprimă acţiunea funcţiei în argumentele ei.

Exemple: funcţia f(x)=x+2: λ x. x + 2 .


numărul f(3): (λ x. x+ 2) 3

6
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Masina Turing

unitate de
control

a b a b ┴ ┴ ┴

7
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

8
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Maşina Turing
Un sistem ( , , Q, q0, F, ) unde:
  este o mulţime finită, nevida numită alfabet de intrare;
  este o mulţime finită, nevida numită alfabetul benzii;
  ,    şi    ;
 Q este o mulţime finită, nevida numită mulţimea stărilor
masinii;
 q0  Q este starea iniţială;
 F  Q este mulţimea stărilor finale (de acceptare sau de
respingere);
 : Q x   Q x  x { L , R } este funcţia de tranziţie, unde L
denota deplasarea la stânga iar R denota deplasarea la
dreapta a cursorului masinii.

9
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare
Stephan Cole KLEENE: "The Theory of Recursive
Functions, Approaching its Centennial", Bulletin (New
Series) of the American Mathematical Society, Vol. 5,
No. 1, July 1981:
"părinţi" teoriei funcţiilor recursive (inafara lui Kurt Gödel şi
Kleene însuşi) sunt consideraţi a fi:
 Leopold Kronecker, prin conferinţa ţinută pe 21
sept. 1886 în faţa Der Deutschen
Naturforscherversammlung zu Berlin (Asociaţia
pentru Cercetarea Naturii), cf. H. Weber, Leopold
Kronecker, Math. Ann. 43 (1893), 1-25
 Julius Wilhelm Richard Dedekind (1831–1916),
prin Teorema 126 ("Satz der Definition durch
Induktion") din articolul "Was sind und was sollen
die Zahlen? (Ce sunt şi ce ar trebui sa fie
numerele)" publicat în 1888 si prin Definitia 71
(care contine defiinitia axiomatica a N i.e.
axiomele Dedekind-Peano)
10
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Exemple de functii primitiv recursive:


a+0 = a
a+succ(x) = succ(a+x)

a ∙0 = 0
a ∙ succ(x) = a ∙ x+a

a 0= 1
a succ(x) = a x ∙ a
unde succ(x)=x+1 .

11
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Recurenta primitiva
Fie funcţiile : g : N n  N , h : N n+2  N ;
se cere să se construiască funcţia
f : N n+1  N
care să satisfacă următoarele două ecuaţii :
(1) f(a1 ,a2 ,…, an ,0) = g(a1 ,a2 ,…, an) ,
(2) f(a1 ,a2 ,…, an , x+1) = h(a1 ,a2 ,…, an , x , f(a1 ,a2 ,…, an , x)) .

Spunem că f este definită prin recurenţă primitivă asupra lui x din


funcţiile g şi h , prin intermediul a n>=0 parametri a1 ,a2 ,…, an .
Convenim ca în cazul n=0 să notăm prin g o constantă număr
natural.
12
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Compunerea functionala
Fie n , m două numere naturale.
Se dau m+1 funcţii de n argumente:
h : N m → N , g i: N n → N , 1 ≤ i ≤ m
Funcţia
f:Nn→N
este definită prin compunere funcţională din funcţiile h , g1 , g2 ,…, gm
dacă şi numai dacă:
f(x1 ,x2 ,…, xn ) = h (g1(x1 ,x2 ,…, xn ), g2(x1 ,x2 ,…,xn ),…,gm(x1 ,x2 ,…, xn
))
Un caz particular de compunere functionala:
subtitutia (m=1)
13
f(a1 ,a2 ,…, an ,0) = g(a1 ,a2 ,…, an) ,
f(a1 ,a2 ,…, an , x+1) = h(a1 ,a2 ,…, an , x , f(a1 ,a2 ,…, an , x)) .
f(x1 ,x2 ,…, xn ) = h(g1(x1 ,x2 ,…, xn ), g2(x1 ,x2 ,…,xn ),…,gm(x1 ,x2 ,…, xn ))

Exemplul 1:
sum(a,x) = a+x,
=> n=1, a1=a
=> sum (a,0) = a+0 = a => g(a) = a = p1(1)(a) ,
sum(a,x+1)=a+(x+1)=(a+x)+1
=>h(a,x,y)=succ(sum(a,x))=succ(p3(3)(a,x,sum(a,x))).
=> sum(a,0)=p1(1)(a) ,
sum(a,x+1)=h(a,x,sum(a,x)) , unde h:N3  N , h(a,x,y)=(succ0p3(3))(a,x,y).

Exemplul 2:
|x-y| = max(0,x-y)+max(0,y-x),
=> |x-y|= max(0, P(2)1 (x,y)-P(2) 2(x,y)) + max(0, P (2) 2(x,y)-P(2)1(x,y)).

14
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Exemplul 3:
O funcţie general recursivă: funcţia Ackermann-
Peter:
n  1, m0

ack (m, n)  ack (m  1,1), n0
ack (m  1, ack (m, n  1)), altfel

int ack(int m, int n)


{
if (0==m) return n+1;
if (0==n) return ack(m-1,1);
return ack(m-1,ack(m,n-1));
}

15
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Exemplul 4 (Conjectura lui Collatz, 1937)


Se dă şirul de numere a0 ,a1 ,…,an , … definit prin
iteraţia pură:
a0  a
 a / 2, daca an este par ,
an 1   n
3  an  1, altfel .

Pentru orice număr natural a există un index n astfel


încât
an=1
Verificata pe calculator pana la 20 × 258 ≈ 5.764 × 1018

16
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare
Functia lui COLLATZ :
este definita prin:
f(n)= n/2, daca n este par,
f(n)= 3*n+1, daca n este impar
şi are urmatoarele propretati:
lungimea secventei de numere generata in vederea atingerii valorii 1 un
se poate calcula pintr-o formula bazata pe datele de intrare
tinde catre 1.
Se cere sa se scrie un program care sa citeasca o pereche de valori naturale nenule,
reprezentand primul si ultimul numar intr-o secventa inchisa de numere naturale.
Pentru fiecare astfel de secventa inchisa, se cere sa se deteremine valoarea care
genereaza cea mai lunga serie cu functia de mai sus, inainte de a ajunge la 1.
Cea mai mare valoare din secventa si din sirul transformarilor nu va depasi tipul long.
http://gfredericks.com/math/Arith/collatzPage.html

17
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare
#include <iostream.h>
long int length (long int n)
{
long int aux=1;
if (n%2) n=n*3+1; else n/=2;
while(n-1){
if (n%2) n=n*3+1; else n/=2;
aux++;
}
return aux;
}
void main ()
{
long int n,m,max,l,i;
cin>>n>>m; max=0; l=-1;
for (i=n; i<=m; i++)
if (length(i)>l) {
max=i; l=length(i);
}
cout<<"intre "<<n<<" si "<<m<<" ,"<<max<<" are lungimea maxima"<<l<<endl;
}
Intre 1 si 20 , numarul 18 are ofera lungimea maxima: 20 18
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Mulţimea funcţiilor de bază


este formată din:

 funcţia succesor succ : N  N , succ(x)=x+1

 funcţiile constante ca (n): N n  N , ca (n) (x1 ,x2 ,…, xn )=a

 funcţiile proiecţie pi (n): N n  N , pi (n) (x1 ,x2 ,…, xi ,…, xn )= xi ,


unde a , n , m  N , 1  i  n, 1jn.

19
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Clasa funcţiilor primitiv recursive


este cea mai mică familie de funcţii f : N n → N , n>=1,
care
 conţine mulţimea funcţiilor de bază şi

 este închisă faţă de operaţiile de

 compunere funcţională şi
 recurenţă primitivă.

 Dedekind (1888) şi Peano (1889),


 Skolem: (1923),
 Gödel (1931),
 Peter (1934).

20
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Următoarele funcţii si predicate sunt primitiv recursive:


a) f:N 2N , f(x,y)=x+y
b) f:N 2N , f(x,y)=x*y
c) f:N 2N , f(x,y)=xy , (x0=1)
d) pd:NN , pd(x)=max(0,x-1)
e) f:N 2N , f(x,y)=max(0,x-y) , (diferenţa aritmetică)
f) sg:NN , sg(0)=0 , sg(x)=1, x>0 ,
g) f:N2N , f(x,y)=|x-y| , (modulul)
h) sqrt:NN ,  
sqrt( x)  x
i) ls,gr,eq:N 2{0,1}, ls(x,y)=1, daca x<y, ls(x,y)= 0, altfel
gr(x,y)=1, daca x>y, gr(x,y)=0, altfel
eq(x,y)=1, daca x=y, eq(x,y)=0, altfel
21
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Scheme de recurenţă speciale:


 recurenţa ereditară
 recurenţa simultană

22
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Schema de recurenţă ereditară


Exemplu:
Considerăm şirul lui Fibonacci:
u0=u1=1 ,
un+2=un+1+un.

23
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Limbajul Borland Pascal Limbajul C/C++


{fib1.pas : implementarea rec. } //fib1.cpp : implementarea rec.
function Fib (n: integer): integer; long Fib (long n)
{returneaza al n-lea termen din // returneaza al n-lea termen al
sirul lui Fibonacci, n0} sirului lui Fibonacci, n0
begin {
if (n<=1) then Fib := n if (n<=1) return n;
else Fib:=Fib(n-1)+Fib(n-2); else return Fib (n-1) + Fib (n-2);
end; }

24
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Limbajul Borland Pascal Limbajul C/C++


{fib2.pas: implementarea iterativa} // fib2.cpp : implementarea iterativa
function Fib (n: integer): integer; long Fib (long n)
var crt, old, older : integer; {
if (n<=1) return n;
begin
long crt, old=1, older=0;
old : = 1; older : = 0; while(n-- >1)
while (n > 1) do {
begin crt = old +older;
crt : = old +older; older = old;
older : = old; }
dec(n) return crt;
end; }
end;
25
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Definitie
x x x
Fie x0, x1,…, xk N. Numarul natural n  p0 0  p1 1  ...  p k k
se numeste numărul Gödel asociat şirului (x0, x1,…,x k) şi
se notează cu <x0,x1,…,xk>.
Exemple: <3,1,2> = 23∙31∙52 = 600,
<1,2,0,5> = 21∙32∙50∙75 = 2898918
Definiţie:
Funcţia f:Nn+1 N se obţine prin recurenţă ereditară din funcţiile
g : Nn N şi h : Nn+2 N dacă:
f(x ,0) = g(x) ,
f(x ,y+1) = h(x ,y ,<f(x ,0) ,…, f(x ,y)>) ,
unde xNn iar <…> desemneaza numarul Gödel asociat
sirului f(x,0), … ,f(x,y).
26
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Teoremă:
Clasa funcţiilor primitiv recursive este închisă faţă de
recurenţa ereditară.

Corolar:
Funcţia f: N  N, f(n) = un este primitiv recursivă.

27
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Schema de recurenţă simultană


Exemplu:
Considerăm ecuaţia lui Pell:
x2-dy2=1, unde x,y  N , a>1, d=a2-1.

Propoziţie:
Perechea (x,y) N 2 este o soluţie pentru ecuaţia lui Pell
dacă există un număr n≥0 astfel încât
x = xn , y = yn , unde :
x0 = 1, y0 = 0 ,
xn+1 = a.xn + d.yn ,
yn+1 = xn + a.yn ,  x 0 .

28
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

program rec_indirecta;
var a,d,n: integer;
function y (n: integer): integer; forward;
function x (n: integer): integer;
begin
if n=0 then x:=1
else x:=a*x(n-1)+d*y(n-1)
end; {x}
function y (n: integer): integer;
begin
if n=0 then y:=0
else y:=x(n-1)+a*y(n-1)
end; {y}
begin {programul principal}
writeln ('dati constanta a > 1 si ordinul solutie n = '); readln (a,n);
d := a *a - 1;
writeln ('perechea de solutii de ordinul ',n,' este: (',x(n):4,' , ',y(n):4,').');
readln;
end.

29
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Definiţie:
Funcţiile fi : N n+1 N, (i=1,2) sunt definite prin recurenţă simultană
din funcţiile gi : N n N şi hi : N n+3 N (i=1,2) dacă
fi(x,0)=gi(x),
fi(x,y+1)=hi(x, f1(x,y), f2(x,y)) , (i=1,2).

Teoremă:
Clasa funcţiilor primitiv recursive este închisă faţă de recurenţa
simultană.
Corolar:
Funcţiile f1,f2: N  N, f1(n) = xn, f2(n)=yn sunt primitiv recursive.

30
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Conceptul de subprogram de tip funcţie cu apel recursiv.

Forma generală a unui subprogram de tip funcţie recursiv:


function f()
{
calcul initial;
conditie de oprire;
apel recursiv f();
calcul final;
return rezultat;
}

31
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Tipuri de subprograme recursive


(1) bazate pe funcţii (primitiv) recursive unare, (funcţia se apelează pe ea însăşi în mod
direct, ca în cazul calculării factorialului);

(2) bazate pe funcţii (primitiv) recursive de mai multe argumente (ca în cazul calculării
cmmdc pentru două numere naturale);
acestea sunt cunoscute sub numele de recursivitate liniară directă:

int cmmdc1 (int x, int y)


{ if (x==y) return x;
else
if (x>y) return cmmdc1(x-y, y);
else return cmmdc1(x, y-x);
}
int cmmdc2 (int x, int y)
{if (0==y) return x;
else
return cmmdc2(y, x%y);
}
32
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare
(3) bazate pe funcţii care se apelează una pe alta (recursivitatea
simultana, numita si recursivitate indirectă), ca in cazul calcularii
solutiilor ecuatiei lui Pell: x2-dy2=1, unde x,y  N , a>1, d=a2-1),

int x(int n)
{
if (n==0) return 1;
return a*x(n-1)+d*y(n-1);
}
int y(int n)
{
if (n==0) r eturn 0;
return x(n-1)+a*y(n-1);
}

33
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

(4) bazate pe funcţii care au nevoie de mai multe valori anterioare pentru
a calcula valoarea curentă (recursivitatea ereditara, numita si
recursivitatea neliniară sau în cascadă), ca în cazul determinării unui
element al şirului lui Fibonacci după formula:
int fibonacci (int n)
{
if (n<=1) return 1;
return fibonacci(n-1) + fibonacci(n-2);
}

34
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Un subprogram recursiv trebuie să respecte următoarele


reguli:
1. subprogramul trebuie să poată fi executat, cel puţin într-o
situaţie, fără a se autoapela;
2. subprogramul recursiv se va autoapela într-un mod în care se
tinde spre ajungerea în situaţia de execuţie fără autoapel.
Pentru a permite apelarea recursivă a subprogramelor
limbajele de programare dispun de mecanisme speciale
 de suspendare a execuţiei programului apelant,
 de salvare a informaţiilor necesare şi
 de reactivare a programului suspendat.

35
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Stiva implicita = zona de memorie


Pentru implementarea recursivităţii în care se poate face salvarea
se foloseşte o stivă. temporară a unor valori, organizată
după principiul LIFO

 La fiecare apel recursiv al unui


subprogram se salvează în stivă starea
curentă a execuţiei sale (adresa de
revenire şi contextul programului).

Adresa de revenire = adresa


instrucţiunii cu care va continua
programul întrerupt la reluarea
execuţiei sale

Context = valorile variabilelor locale


subprogramului, valorile parametrilor
de tip valoare şi adresele parametrilor
de tip referinţă
3
6
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

 Deşi variabilele locale ale subprogramului apelat au aceiaşi


identificatori cu cei ai subprogramului apelant, orice referire la
aceşti identificatori se asociază ultimului set de variabile alocate
în stivă.

 Zona din stivă rămâne alocată pe tot parcursul execuţiei


subprogramului apelat şi se dealocă în momentul revenirii în
programul apelant.

 Stiva nu este gestionată explicit de programator ci de către


limbaj.

 La terminarea execuţiei subprogramului apelat recursiv se


reface contextul programului din care s-a făcut apelul.
37
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Datorită faptului că la fiecare autoapel se ocupă o zonă de


stivă, recursivitatea este eficientă numai dacă numărul de
autoapeluri nu este mare, astfel încât să nu se ajungă în situaţia
umplerii stivei.

 Recursivitatea oferă avantajul unor soluţii mai clare pentru


probleme şi unei lungimi mai mici a programelor.

Ea prezintă însă dezavantajul unui timp mai mare de execuţie


şi a unui spaţiu de memorie ocupat mai mare.

38
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Ce se întâmplă la autoapelul funcţiei/procedurii?


 Prin autoapelul funcţiei/ procedurii instrucţiunile
rămân neschimbate.
 Procedura/funcţia va prelucra datele transmise în stivă.
 In cazul unui nou autoapel, se creează un nou nivel
pentru stivă, în care se depun noile valori.
 Procedura/funcţia care s-a autoapelat se reia de la
instrucţiunea care urmează autoapelului şi va lucra cu
variabilele (valorile) reţinute în stivă în momentul
autoapelului, la care se adaugă valorile returnate.
 La atingerea unuia dintre cazurile de bază (condiţia de
oprire), urmează să se revină din autoapelări. 39
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Demonstrarea corectitudinii algoritmilor recursivi:


 se face intr-un mod similar demonstrarii corectitudinii
algoritmilor nerecursivi;
 este mult simplificată de forma algoritmului (care permite
utilizarea comodă a metodei inducţiei matematice
complete):
 se verifică mai întâi dacă toate cazurile particulare (de
terminare a apelului recursiv) funcţionează corect;
 se trece apoi la o verificare formală, prin inducţie, a
funcţiei recursive corespunzătoare, pentru restul cazurilor.

40
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Exemplificare: calculul factorialului unui număr


int factorial (int n)
{
if (0==n) return 1;
return n*factorial(n-1);
}
Demonstrarea corectitudinii: doi pasi:
 pentru n = 0, valoarea 1 returnată de program este corectă;
 dacă n>1 atunci, presupunând corectă valoarea returnată
pentru (n-1), prin înmulţirea acesteia cu n se obţine valoarea
corectă a factorialului numărului natural n, valoare returnată de
subprogram.
În ambele situaţii este satisfăcută condiţia de oprire.

41
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Algoritmul căutării binare: un exemplu algoritm proiectat prin


aplicarea tehnicii recursivitatii si a metodei divide-et-impera:
Fie a1, a2, …, an un şir ordonat de n numere naturale (nN,
n≥2) si fie x un numar natural, dat . Se cere sa se
verifice daca numarul x se afla printre elementele sirului.
Metoda:
se injumatateste “intervalul” [[a1, an]] si se caută x în jumătatea
“cea mai apropiată” de valoarea acestuia;
urmeaza divizarea recursivă a acestei jumătăţii în alte două jumătăţi
“mai mici” şi reluarea procedeului pana la gasirea elementului sau
pana cand domeniul cautarii devine vid.
42
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

LIMBAJUL C++ Observam respectarea regulilor descrise mai sus:


1. Cazul de bază.
Undeva în funcţia recursivă, există unul sau mai multe
// bs.cpp: algoritmul recursiv de cautare
binara teste prin care se verifică conditiile de ieşire din autoapelul
recusiv. Aceste teste de ieşire se numesc cazuri de bază..
int BinarySearch (float *arr, int n, float x,
int btm, int top)
{ Cu ajutorul acestor cazuri se va şti dacă valoarea căutată în
if ( top>=btm ) şir s-a găsit sau nu şi se poate returna rezultatul imediat.
{ int mid=(top+btm)/2;
if (arr[mid]==x) 2. Prelucrarea progresivă.
Esenţa definiţiei recursive constă în faptul că
return mid; //cautare cu succes
pentru rezolvarea cazului n+1 se recurge la cazul
if (arr[mid]<x)
n. In acest fel, celelalte cazuri ale recursivităţii,
btm=mid+1; diferite de cazurile de bază, trebuie rezolvate prin
else top=mid-1; tratarea lor astfel încât procesul apelului recursiv
return BinarySearch(arr, n, x, btm, top) ; să le orienteze către unul dintre cazurile de bază.
}
else return -1; //nu s-a gasit valoarea Variabilele top şi btm sunt prelucrate astfel
cautata încât căutarea să se realizeze într-o porţiune din
} ce în ce mai mică a şirului, până când unul dintre
cazurile de bază este găsit. 43
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

LIMBAJUL BORLAND PASCAL

{ bs.pas: algoritmul recursiv de cautare binara }


function BinarySearch (arr:real; n: integer; x:real;
btm, top:integer) : integer;
var mid : integer;
begin
if (( top>=btm ) then
begin
mid : = (top+btm) div 2;
if (arr[mid] = x) then BinarySearch : = mid;
if (arr[mid]<x) then btm : = mid+1
else top : = mid-1;
BinarySearch:=BinarySearch(arr,n,x,btm, top)
end;
else BinarySearch : = -1;
end;
44
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

 Ridicarea unui număr real x la o putere n naturală, xn binare: un


alt exemplu algoritm proiectat prin aplicarea tehnicii
recursivitatii si a metodei divide-et-impera:

 Metoda clasică de ridicare la putere este multiplicarea sa cu el însuţI


de n-1 ori, iar algoritmul este de complexitate O(n).

45
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

 Tehnica divide-et-impera: se poate obţine un algoritm cu complexitate:


 O(log(n)).

 Strategia se bazează pe următoarele proprietăţi ale puterilor întregi:

 
n
1) x  1
0
2) x  x
1
3) x 
n
x 2 2
, daca n este par 4) x n  x n -1x, daca n este impar

Cazurile care reprezintă Când n este par se Când n este impar se


calculează mai întâi xn-1 multiplică x cu el însuşi (x2)
cazurile de bază ale recursivităţii.
şi apoi se multiplică şi apoi rezultatul se ridică
rezultatul cu x. recursiv la puterea n/2.

 Se observă cum valorile lui n scad, până când atinge unul dintre
cazurile de bază.

46
 
n
1) x  1
0
2) x  x
1
3) x 
n
x 2 2
, daca n este par 4) x n  x n -1x, daca n este impar

LIMBAJUL BORLAND PASCAL LIMBAJUL C++

{pow1.pas functia putere recursiva } //pow1.cpp functia putere recursiva


function Power(x:real; n :integer): real; float Power(float x, int x)
begin {
if (n=0) then power:=1; if (n==0) return 1;
if (n=1) then power:=x; if (n==1) return x;
if odd ( n) then if (n&1)
Power:=Power(x,n-1)*x; {n impar} return Power(x,n-1)*x; //n impar
Else Power:=Power(x*x, n/2); {n par} else return Power(x*x, n/2); //n par
end; }

47
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Pentru a tranforma o funcţie recursivă într-o funcţie iterativă:


1. se defineşte o stivă şi se initializează cu
mulţimea vidă; void print_rec()
2. cât timp este îndeplinită condiţia de {
continuare a recursivităţii: int c = getch ();
3. se execută instrucţiunile dinainte de
apel;
if (c!=’\n’) { print_rec(); printf(“%c”,c);
}
4. se salveaza pe stivă valorile actuale ce
reprezintă argumentele funcţiei }
recursive; void print_it ()
5. se execută instrucţiunile funcţiei {
recursive; Stack S;
6. se modifică argumentele funcţiei empty (S);
recursive;
7. când condiţia nu mai este indeplinită şi int c = getch ();
dacă stiva este nevidă atunci while (c!=’\n’) { push(c); c = getch();
8. se aduce de pe stiva un set de variabile, }
9. se executa o serie de calcule (cele de while (nevida(S)) {c=pop (S);
după apelul recursiv) şi printf (“%c”,c);}
10. se trece la pasul 3. }
11. dacă stiva este vidă algoritmul se opreşte. 48
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Avantajele si dezavantajele utilizarii subprogramelor recursive


 Exista o legatura stransa intre  Recursivitatea trebuie inlocuita
recursivitate si structurile de date prin iteratie atunci cand
de tip stiva, arbore, etc folosite in recursivitatea este prea adanca
limbajele Borland Pascal si C++ sau cand limbajul de programare
pentru reprezentarea functiilor / nu permite implementarea de
procedurilor recursive (insasi apeluri recursive.
definitia stivelor, arborilor, listelor  Din punctul de vedere al memoriei
realizandu-se recursiv). solicitate, o varianta recursiva
 Deseori, variantele iterative necesita un spatiu de stiva
necesita folosirea explicita a suplimentar pentru fiecare apel
structurii de tip stiva, generand fata de varianta iterativa.
astfel un cod extrem de laborios.  Dimensiunea stivei trebuie aleasa
In aceste situatii se considera astfel incat sa poata permite
solutia recursiva mai eleganta, memorarea elementelor pentru
datorita simplitatii sale. toate iteratiile.
49
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Greseli tipice in realizarea subprogramelor recursive (1):


1. Declararea ca variabile globale a unor variabile care
controleaza adresa de revenire (cazul cand apelurile se
fac din interiorul unei structuri repetitive).
2. Declararea ca parametri transmisi prin valoare sau ca
variabile locale a unor date structurate (de exemplu de tip
tablou) micsoreaza semnificativ adancimea acceptata a
recursivitatii, deoarece memorarea lor necesita un spatiu
mare de memorie.

50
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

Greseli tipice in realizarea subprogramelor recursive (2):


4. Absenta unei conditii de oprire.

5. Exprimarea unei conditii de oprire in care nu intervin nici


variabile locale si nici parametrii transmisi prin valoare sau
prin referinta ai subprogramului.
6. Marirea dimensiunii problemei prin transmiterea in cadrul
autoapelurilor a unor parametri actuali care nu tind sa se
aproprie de valorile impuse prin conditia de oprire.
7. Neutilizarea directivei forward (limbajul Borland Pascal) in
cazul declararii unor subprograme indirect recursive

51
1. Algoritmi: generalitati
2. Algoritmi: modele de calculabilitate
3. Teoria functiilor recursive
4. Scheme de recurenta; reduceri
5. Recurenţă şi iteraţie in programare

BIBLIOGRAFIE
1. Răzvan ANDONIE, Ilie GARBACEA: Algoritmi
fundamentali. O perspectivă C++, Editura Libris, Cluj-
Napoca, 1995.
2. Cristian Sorin CALUDE: Theories of Computational
Complexity, Elsevier Science Publ., Amsterdam, 1988.
3. Richard JOHNSONBAUGH, Marcus SCHAEFER:
Algorithms, Pearson Prentice Hall, Upper Saddle River, NJ.,
2004.
4. D. JOYCE: The Dedekind/Peano Axioms, Clark University,
posted on January 2005,
http://aleph0.clarku.edu/~djoyce/numbers/peano.pdf
5. Dexter C. KOZEN: Theory of Computation, Springer-Verlag,
Berlin Heidelberg, 2006.
52

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