Didaxis
lecție · Informatică

Recursivitate

Recursivitatea este proprietatea unui subprogram de a se autoapela, direct sau prin alt subprogram. O funcție recursivă rezolvă problema pentru n folosind rezultatul aceleiași probleme pentru o valoare mai mică, până la un caz simplu, rezolvat direct, numit condiție de oprire. De exemplu, n! = n · (n − 1)!, iar 0! = 1.

Se face în:
Clasa a X-a
Clasa a XI-a
Actualizat la: 30 octombrie 2026
1pe scurtstratul 1 din 3 · rezumatul lecției

Pe scurt

Recursivitatea apare când un subprogram se apelează pe sine pentru o problemă mai mică. Sunt necesare un caz de oprire și un pas care se apropie de el. Pentru factorial, și când . Astfel .

Ce Exemplu
Definiția recursivă n! = n · (n − 1)!, cu 0! = 1
Funcția recursivă int fact(int n) { if (n == 0) return 1; return n * fact(n - 1); }
Condiția de oprire cazul rezolvat direct, fără autoapel (n == 0)
Autoapelul trebuie să se apropie de condiția de oprire (n - 1)
Instrucțiuni înainte de autoapel se execută la „coborâre”, în ordinea apelurilor
Instrucțiuni după autoapel se execută la „revenire”, în ordinea inversă
Numărul de apeluri se numără și apelul inițial
Desen la lecția „Recursivitate”
2în detaliustratul 2 din 3 · pentru clasă și Bacalaureat

În detaliu

Condiția de oprire și autoapelul

O funcție recursivă are două părți: cazul simplu, rezolvat direct, și cazul general, în care funcția se autoapelează pentru o problemă mai mică. Fiecare autoapel trebuie să se apropie de cazul simplu: la fact(n - 1), n scade cu 1 la fiecare apel, deci ajunge la 0. Dacă cele două părți sunt corecte, funcția e corectă pentru orice n, la fel ca la o demonstrație prin inducție.

Stiva apelurilor

Fiecare apel are propriile copii ale parametrilor și ale variabilelor locale, păstrate pe stivă. Când fact(3) ajunge la fact(2), apelul fact(3) rămâne „în așteptare”, cu n = 3, până când fact(2) returnează. Apelurile se închid în ordinea inversă deschiderii: ultimul deschis, fact(0), se termină primul. De aceea, instrucțiunile scrise înaintea autoapelului se execută la coborâre (3, 2, 1), iar cele scrise după el, la revenire (1, 2, 3).

Recursiv sau iterativ

Orice funcție recursivă se poate scrie și iterativ, cu o structură repetitivă. Varianta recursivă e potrivită când problema e definită recursiv (factorial, cmmdc, parcurgerea unui graf, backtracking), dar fiecare apel costă timp și memorie pe stivă. Când două autoapeluri recalculează aceleași valori, numărul de apeluri explodează: F(n) = F(n − 1) + F(n − 2), calculat naiv, face 109 apeluri pentru F(10) și 1 664 079 pentru F(30) (exemplul 4).

Exemplu — numărul de apeluri pentru F(5). Dacă numără apelurile, , iar pentru . Rezultă , și . Calculul include și apelul inițial, nu numai autoapelurile.

Recursivitate directă și indirectă

Dacă subprogramul se apelează pe sine, recursivitatea este directă. Dacă A îl apelează pe B, iar B îl apelează pe A, recursivitatea este indirectă; și aici trebuie să existe o condiție de oprire comună.

Factorialul, limitele lui și varianta iterativă

Exemplu — factorialul lui 4. Implementarea factorialului păstrează câte un cadru pe stiva apelurilor, până la atingerea cazului de bază:

#include <iostream>
using namespace std;
long long factorial(int n) {
    if (n == 0) return 1;
    return n * factorial(n - 1);
}
int main() {
    int n;
    cin >> n;
    cout << factorial(n);
    return 0;
}

Pentru intrarea 4, apelurile coboară factorial(4) → factorial(3) → factorial(2) → factorial(1) → factorial(0). Cazul de bază întoarce 1, iar rezultatele urcă: . Ieșirea este 24. Fiecare apel păstrează propria valoare a parametrului n până când apelul interior se încheie. Timpul este proporțional cu , iar stiva ocupă spațiu proporțional cu . Programul presupune : pentru argumentul s-ar îndepărta de 0 și apelurile nu s-ar opri, iar pentru valoarea depășește tipul long long.

Fiecare apel păstrează propria valoare a parametrului n până când apelul interior se încheie. Când se ajunge la cazul de bază, nu mai apare un apel nou; la revenire, fiecare nivel face o singură înmulțire. Pentru un n admis, timpul este , iar stiva de apeluri ocupă spațiu. Programul presupune : la n<0, argumentul s-ar îndepărta de 0 și apelurile nu s-ar opri, iar peste 20 valoarea nu încape în tipul folosit. Varianta iterativă înmulțește de la mic la mare, fără apeluri pe stivă, cu memorie auxiliară .

Exemple rezolvate

Exemplul 1: factorialul, cu apelurile urmărite

Calculează 5! recursiv.

  1. fact(5) = 5 · fact(4) = 5 · 4 · fact(3) = … = 5 · 4 · 3 · 2 · 1 · fact(0).
  2. fact(0) returnează 1, apoi valorile se înmulțesc la revenire: 1, 1, 2, 6, 24, 120.
#include <iostream>
using namespace std;

int fact(int n) {
    if (n == 0)
        return 1;                  // conditia de oprire
    return n * fact(n - 1);        // autoapelul, pentru o valoare mai mica
}

int main() {
    cout << fact(5) << "\n";
    return 0;
}

Programul afișează:

120

Exemplul 2: suma cifrelor, recursiv

Suma cifrelor lui n este ultima cifră plus suma cifrelor lui n / 10, iar suma cifrelor lui 0 este 0.

#include <iostream>
using namespace std;

int sc(int n) {
    if (n == 0)
        return 0;
    return n % 10 + sc(n / 10);
}

int main() {
    cout << sc(52816) << "\n";
    return 0;
}

Programul afișează:

22

Aceeași funcție, scrisă iterativ, este în lecția despre subprograme.

Exemplul 3: ordinea afișărilor

Ce afișează apelul f(3)?

#include <iostream>
using namespace std;

void f(int n) {
    if (n > 0) {
        cout << n;      // la coborare
        f(n - 1);
        cout << n;      // la revenire
    }
}

int main() {
    f(3);
    cout << "\n";
    return 0;
}
  1. La coborâre se afișează 3, 2, 1, câte o cifră înaintea fiecărui autoapel.
  2. f(0) nu face nimic. La revenire, fiecare apel își afișează propriul n, de la ultimul deschis la primul: 1, 2, 3.
321123

Exemplul 4: câte apeluri face Fibonacci, scris naiv

Șirul lui Fibonacci are F(1) = F(2) = 1 și F(n) = F(n − 1) + F(n − 2). Câte apeluri face funcția recursivă pentru F(10)?

  1. Fiecare apel pentru n > 2 face două autoapeluri, iar valorile mici se recalculează de multe ori: F(8) se calculează de 2 ori, F(7) de 3 ori.
  2. Numărând toate apelurile, inclusiv pe cel inițial, se obțin 109 apeluri pentru F(10) = 55.
#include <iostream>
using namespace std;

int apeluri = 0;

int fib(int n) {
    apeluri++;
    if (n <= 2)
        return 1;
    return fib(n - 1) + fib(n - 2);
}

int main() {
    int n;
    cin >> n;
    int r = fib(n);
    cout << r << " " << apeluri << "\n";
    return 0;
}

Pentru intrarea 10, programul afișează valoarea și numărul de apeluri:

55 109

Pentru 30 afișează 832040 1664079. O buclă care ține doar ultimii doi termeni face 28 de pași pentru același rezultat.

Exemplul 5: nivel de examen, o funcție recursivă pe cifre

Se consideră funcția de mai jos. Ce valoare returnează f(2468013) și câte apeluri ale lui f se fac în total?

#include <iostream>
using namespace std;

int nr = 0;

int f(int n) {
    nr++;
    if (n == 0)
        return 0;
    if (n % 2 == 0)
        return f(n / 10) + 1;
    return f(n / 10);
}

int main() {
    cout << f(2468013) << " " << nr << "\n";
    return 0;
}
  1. Funcția elimină câte o cifră la fiecare apel și adaugă 1 când ultima cifră e pară, deci numără cifrele pare.
  2. Cifrele pare ale lui 2468013 sunt 2, 4, 6, 8 și 0: funcția returnează 5.
  3. Numărul are 7 cifre, deci sunt 7 apeluri care elimină câte o cifră, plus apelul final cu n = 0: 8 apeluri.
5 8
3pentru admiterestratul 3 din 3 · pentru examene

Pentru admitere

Pentru intrarea 4, stiva primește în ordine argumentele 4, 3, 2, 1, 0. Revenirea calculează în ordine 1, 1, 2, 6, 24, iar rezultatul este 24. Varianta iterativă pornește cu produs = 1 și înmulțește succesiv cu 1, 2, 3, 4; obține tot 24, în timp proporțional cu și cu spațiu auxiliar constant. Pentru orice recursie, verifică atât cazul de bază, cât și faptul că argumentul fiecărui apel se apropie de el. Când o funcție afișează înainte sau după apelul recursiv, ordinea afișărilor diferă: afișarea dinaintea apelului produce valorile în ordinea apelurilor, iar cea de după, în ordinea revenirilor. Pentru void scrie(int n) cu afișarea înainte de apel, scrie(3) produce 321; cu afișarea după apel, produce 123. Dacă un apel are două apeluri recursive, ca la Fibonacci, desenează arborele apelurilor și numără frunzele.

Exemplu în formatul examenului. Ce se afișează în urma executării programului de mai jos?

#include <iostream>
using namespace std;
int f(int n) {
    if (n <= 0) return 0;
    return n % 10 + f(n / 10);
}
int main() {
    cout << f(2345);
    return 0;
}
  • a) 5
  • b) 14
  • c) 5432
  • d) 2345

Răspunsul corect este b). Apelurile sunt f(2345), f(234), f(23), f(2) și f(0). Funcția adună ultima cifră a fiecărui argument: , iar f(0) întoarce 0. Varianta c) ar fi un număr format din cifrele în ordine inversă, nu o sumă, iar varianta a) ar apărea dacă funcția ar returna numai prima cifră extrasă.

Cazul de bază contribuie la rezultat: dacă funcția din exemplu ar întoarce 1, nu 0, pentru , atunci f(2345) ar fi , nu 14.

Unde apare la examen

Greșeli frecvente

  • Greșit: o funcție recursivă nu are nevoie de un caz de oprire.
    Corect: fără caz de bază apelurile nu se mai opresc.
  • Greșit: apelurile recursive nu ocupă memorie suplimentară.
    Corect: fiecare apel adaugă un cadru pe stiva apelurilor.
  • Greșit: cazul de bază este întotdeauna n = 1.
    Corect: depinde de problemă; la factorial este n = 0, cu 0! = 1.
  • Greșit: cazul de bază este opțional, iar lipsa condiției de oprire nu strică.
    Corect: fără o oprire atinsă, funcția se autoapelează la nesfârșit, până se umple stiva și programul se oprește cu eroare.
  • Greșit: fact(n) în loc de fact(n - 1), sau o funcție pe cifre care nu împarte la 10.
    Corect: autoapelul se apropie de oprire; altfel funcția nu se termină niciodată.
  • Greșit: fact(n - 1); return n;.
    Corect: rezultatul autoapelului trebuie folosit, deci scrii return n * fact(n - 1);.
  • Greșit: ce e scris după autoapel se execută în ordinea apelurilor.
    Corect: se execută la revenire, adică în ordinea inversă apelurilor (exemplul 3).
  • Greșit: la numărarea apelurilor se omite primul apel.
    Corect: se numără și apelul inițial, cel din main.
  • Greșit: Fibonacci recursiv naiv pentru valori mari, când există o soluție iterativă simplă.
    Corect: pentru n = 50 face miliarde de apeluri.
  • Greșit: factorial(4) întoarce 4 la prima intrare în funcție.
    Corect: așteaptă rezultatul apelului cu 3.
  • Greșit: toate apelurile folosesc aceeași variabilă locală n.
    Corect: fiecare apel are propria instanță.
în contul tăuPremium

Testează-te pe această lecție

Lecția o citești aici, fără cont. Testele pe lecții și capitole sunt în cont, cu grile originale Didaxis și explicația fiecăreia: gratuit 10 grile pe zi, fără limită cu Premium, 49 de lei pe lună pentru fiecare copil.

Înainte și după

Întrebări frecvente

Ce este condiția de oprire la o funcție recursivă?
Este cazul în care funcția returnează rezultatul fără să se mai autoapeleze, de exemplu n = 0 la factorial. Fără ea, sau dacă autoapelurile nu se apropie de ea, funcția se autoapelează la nesfârșit, iar programul se oprește cu eroare când se umple stiva.
Ce este mai bine: recursiv sau iterativ?
Depinde. Varianta recursivă e adesea mai scurtă și urmează direct definiția, dar fiecare apel ocupă memorie pe stivă. Când apelurile recalculează aceleași valori, ca la Fibonacci scris naiv, varianta iterativă este mult mai rapidă.
Ce este recursivitatea indirectă?
Situația în care un subprogram A apelează un subprogram B, iar B îl apelează la rândul lui pe A. În recursivitatea directă, subprogramul se apelează pe sine.

Surse și referințe

Redactare proprie, conform programei:

  • OMECI 5099/2009, anexa 5, Informatică, p. 4–5, clasa X intensiv; rocnee.eu
  • OMECI 5099/2009, anexa 5, Informatică, p. 4–5, clasa XI; plan de încadrare: OMEC 7723/2024, anexa 2, tabelele 1–25, legislatie.just.ro; filiera tehnologică: OMEC 7724/2024, anexa 4, tabelul calificării, legislatie.just.ro
  • UNSTPB, Regulament admitere licență 2026, Anexa II-1.2 p. Anx II-14 și Anexa XI-3 p. Anx XI-6–7 (PDF p. 64, 120–121); admitere.pub.ro
  • OMECTS 4800/2010, anexa 2, Informatică, p. 3–4; edu.ro

Documente consultate

  • UNSTPB, admitere 2026, anexa XI-3, p. Anx XI-6–7
  • Programa școlară de informatică, clasa a XI-a (OMECI 5099/2009, anexa 5), CNCE; rocnee.eu
  • Programa de bacalaureat la informatică, matematică-informatică (anexa 2 la OMECTS 4800/2010), Ministerul Educației, p. 4–5; edu.ro
  • Programele școlare noi de informatică pentru clasele X–XII (OMEC 4370/2026, MO 591 bis/20.07.2026), CNCE; rocnee.eu
  • Subiectele și baremele Bacalaureatului 2026; subiecte2026.edu.ro

Desene: Redactare proprie (desen original), conform Programa școlară de informatică, clasa a XI-a (OMECI 5099/2009, anexa 5), CNCE; rocnee.eu

lecțiile sunt gratuite

Ai citit lecția. Acum verifică-te.