Sunteți pe pagina 1din 18

Există două mari categorii de funcții:

Funcții Iterative Funcții Recursive


• Iterație este atunci când aceeași procedură • în prima fază funcția rulează Iterativ
este reperată de mai multe ori • în corpul funcției există o instrucțiune care reapelează
• execuția unei sarcini se face urmând funcția din care face parte
succesiunea instrucțiunilor din corpul funcției ➢ un obiect sau un fenomen se defineşte în mod recursiv,
• se apelează odată cu funcția în sine dacă în definiţia sa există o referire la el însuşi.
• pentru a ieși din șirul apelurilor, funcția trebuie să conțină o
condiție if de ieșire din succesiunea iterațiilor
• execuţia repetată a unei porţiuni de program, • execuţia repetată a unui modul în cursul execuţiei lui se
până la îndeplinirea unei condiţii, utilizată în: verifică o condiţie, iar nesatisfacerea condiţiei implică
➢ while, do-while (repetări mai lungi, creșteri reluarea execuţiei modulului de la început, fără ca execuţia
neuniforme) curentă să se fi terminat în momentul satisfacerii condiţiei,
➢ for (repetări mai scurte, creșteri uniforme) apoi se revine în ordine inversă în lanţul de apeluri,
reluându-se şi încheindu-se apelurile suspendate.
• structura de date utilizată este Stiva
• diferența dintre cele două variante este utilizarea acestei Stive
➢ Iterația folosește Stiva gestionată de către programator
➢ Recursiva folosește Stiva sistemului de operare
Recursivitatea este folosită cu multă eficienţă în matematică.
Exemple de definiţii matematice recursive:
1. definiţia numerelor naturale:
0 € N dacă i € N,
atunci succesorul lui i € N
2. definiţia funcţiei factorial
fact : N -> N
fact(n) = 1, dacă n=0
= n * fact (n-1), dacă n>0
3. definiţia funcţiei Fibonacci
fib : N -> N
fib(n) = 1, dacă n=0 sau n=1
= fib(n-2) + fib(n-1), dacă n>1
Utilitatea practică a recursivităţii:
• posibilitatea de a defini un set infinit de obiecte printr-o singură relaţie sau printr-un
set finit de relaţii.
Recursivitatea s-a impus în programare odată cu apariţia unor limbaje de nivel înalt,
care permit scrierea modulelor autoapelante
PASCAL, LISP, ADA, ALGOL, C - limbaje recursive
FORTRAN, BASIC, COBOL - limbaje nerecursive

Un program recursiv poate fi exprimat: A = M (A, B), unde M este mulţimea care
conţine instrucţiunile B şi pe A însuşi.
For While
utilizat atunci când se dorește o serie de utilizat atunci când se dorește o iterare
numere întregi succesive sau să se repete până când o anumită condiție este
o procedură de un anumit număr de ori îndeplinită, sau dacă se știe în avans câte
#include <stdio.h> rulări trebuie executate
#include <stdio.h>
int main() {
int i; int main() {
for(i=0; i<10; i++) int i=0;
{printf("%d - %d\n", while(i<10)
i, i*i);} {printf("%d - %d\n", i, i*i);
} i = i+1;}
}
#include<stdio.h>

int main()
{
int i;
for(i=1;i<=10;i++)
{
printf("%5d\n",i);
}
return 0;
}
#include <stdio.h>
int main(void)
{
int i, n;
printf("tabela patratelor.\n");
printf("Scrie limita tabelului:
");
scanf("%d", &n);
i = 1;
while (i <= n)
{
printf("\t%d\t%d\n", i, i * i);
i++;
}
return 0;}
Exprimarea recursivităţii în C:
• funcţia recursivă este o funcţie care se apelează pe ea însăşi direct, în sensul că o
funcţie F conţine o referinţă la ea însăşi indirectă (o funcţie F conţine o referinţă la o
funcţie X care include o referinţă la F)

Se pot deosebi două feluri de funcţii recursive directe:


• Funcţii cu un singur apel recursiv, aceste instrucţiuni se pot rescrie uşor sub formă
nerecursivă (iterativă).
• Funcţii cu unul sau mai multe apeluri recursive, în forma lor iterativă, trebuie să
folosească o stivă pentru memorarea unor rezultate intermediare.
void
#include<stdio.h> int main()
void binar (int n)// afiseaza n în baza 2 {
{ int n;
if (n>0) scanf ("%d",&n);
{ printf ("%d = ", n);
// scrie echivalentul binar al lui n/2 if (n)
binar (n/2); binar(n);
// şi restul impartirii lui n la 2 else
printf ("%d",n%2);} printf("0");
} fflush (stdin);
getchar ();
return 0;
}
#include<stdio.h> int main(){
#include<conio.h> int n, i, f;
printf("Scrie o cifra pentru ai
//Functia recursiva de calcul a factorialului afla factorialul = ");
int fact_rec (int n) { scanf("%d",&n);
if (n==1 || n==0 ) return 1; printf("\n cifra fact rec
return n*fact_rec(n-1);//apel recursiv fact it\n");
} for(i=1; i<=n; i++ )
//Varianta nerecursiva, iterativa printf("%5d %10d %10d\n", i,
int fact_it (int n) { fact_rec(i), fact_it(i));
int i, f; getchar();
for( i=f=1; i<=n; i++ ) return 0;
f *= i; }
return f; Observaţie: tipul funcţiei factorial trebuie
} să devină long pentru n>=16!
Printr-o demonstraţie formală sau testând toate cazurile posibile.
Se verifică întâi dacă toate cazurile particulare funcţionează corect (care se execută
când se îndeplineşte condiţia de terminare a apelului recursiv).
Se face apoi o verificare formală a funcţiei recursive, pentru restul cazurilor,
presupunând că toate componentele din codul funcţiei funcţionează corect.

Exemplu: factorialul
Demonstrarea corectitudinii cuprinde doi paşi:
• pentru n=1 valoarea 1 care se atribuie factorialului, este corectă
• pentru n>1, presupunând corectă valoarea calculată pentru predecesorul lui n
de către fact(n-1), prin înmulţirea acesteia cu n se obţine valoarea corectă a
factorialului lui n.
Observaţii:
• Orice funcţie recursivă trebuie să conţină (cel puţin) o instrucţiune if, de obicei
chiar la început, prin care se verifică dacă (mai) este necesar un apel recursiv sau
se iese din funcţie!
• Absenţa instrucţiunii if conduce la o recursivitate infinită, la un ciclu fără condiţie
de terminare (aceasta ar duce la o eroare de program - depăşirea stivei)
• Pentru funcţiile de tip diferit de void apelul recursiv se face printr-o instrucţiune
return, prin care fiecare apel preia rezultatul apelului anterior!
• Funcţiile recursive nu conţin, în general, cicluri explicite (cu unele excepţii), iar
repetarea operațiilor este obţinută prin apelul recursiv!
void f()
{
f(); //apel infinit
}

apelul este de obicei condiţionat astfel:


void f()
{
// apel finit condiţionat
If (condiţie) f();
}
La fiecare apel al funcţiei sunt puse într-o stivă (gestionată de compilator), adresa de
revenire la variabilele locale și argumentele formale. Acestea fiind referite şi asupra lor
făcându-se modificările în timpul execuţiei curente ale funcţiei. La ieşirea din funcţie
(prin return) se scot din stivă toate datele puse la intrarea în funcţie (se "descarcă" stiva),
modificările operate asupra parametrilor-valoare nu afectează parametrii efectivi de
apel corespunzători.
Pe parcursul unui apel, sunt accesibile doar variabilele locale şi parametrii pentru
apelul respectiv, nu şi cele pentru apelurile anterioare, chiar dacă acestea poartă
acelaşi nume.
Atenţie! Pentru fiecare apel recursiv al unei funcţii se crează copii locale ale
parametrilor valoare şi ale variabilelor locale, ceea ce poate duce la ocuparea
exagerată a memoriei!
Algoritmii recursivi sunt potriviţi în rezolvarea problemelor care utilizează formule
recursive pentru prelucrarea, înțelegerea şi verificarea structurilor de date definite
recursiv (liste, arbori), și a relaţiilor de recurenţă.
Iteraţia este preferată (uneori) datorită vitezei mai mari de execuţie și a spațiului redus
al memoriei folosite.
#include <stdio.h> int main ()
//Factorialul si sirul lui Fibonacci in functie de {
un numar scris de catre utilizator int n, i;
int factorial (int n) { scanf ("%d", &n);
if(n == 0) { return 1; } printf ("Factorial pentru %d:
else { return n * factorial (n-1); %d\n", n, factorial (n));
} } printf ("Fibbonacci pentru %d: " ,
n);
int fibbonacci(int n) for (i = 0;i<n;i++)
{ if(n == 0) {
{ return 0; } printf ("%d ", fibbonacci (i));
else if(n == 1) { return 1; } }
else { return (fibbonacci (n-1) + }
fibbonacci (n-2));
} }
Iterativ Recursiv
long int factIterativ(long int nr) //varianta folosind continue
{ long int i=1; //contor pentru for() if(nr==0 || nr==1)return 1;
long fact=2; fact=1; //se ajunge aici doar daca numarul
este diferit de 0 si 1
//varianta clasica for( ;i<=nr;fact*=i,i++) continue;
if (nr==0 || nr==1) return 1; printf("%d\n", i);
for( ;i<=nr;i++) fact *=i; } return fact; }

//varianta folosind un ciclu infinit intrerupt //varianta recursiva


fortat de break long int factRecursiv(long int nr)
for( ; ; ) { long int fact=1;
{if(nr==0 || nr==1) if(nr==0 || nr==1) return 1;
{fact=1; break;} else return nr*factRecursiv(--nr);
else if(i<=nr){fact*=i;i++;} }
else break;
}

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