Sari la conținut
EduCamp

Tematică științifică · 2.7

Subprograme recursive

Recursivitatea directă și indirectă, mecanismul apelului recursiv pe segmentul de stivă, evoluția parametrilor și a variabilelor locale la funcție și la procedură, adâncimea recursivității, avantajele și dezavantajele, cu planul de idei cerut la examen.

∗ Și la proba practică — Titularizare

Recursivitatea este un mecanism general de elaborare a algoritmilor.

Recursivitate directă și indirectă

Forma generală cuprinde întotdeauna o condiție de oprire și o ramură pe care se face autoapelul.

În C++

tip_returnat nume_functie(lista de parametri) {
    if (conditie_de_oprire)
        instructiune;
    else
        nume_functie(lista de parametri);
}

În Python

def nume_functie(lista de parametri):
    if conditie_de_oprire:
        instructiune
    else:
        nume_functie(lista de parametri)

În C++

Al doilea subprogram trebuie declarat înaintea primului, printr-un prototip: la momentul în care compilatorul citește corpul primului, celălalt încă nu există pentru el.

bool impar(int n);              // prototipul, fara corp

bool par(int n) {
    if (n == 0) return true;
    else        return impar(n - 1);
}

bool impar(int n) {
    if (n == 0) return false;
    else        return par(n - 1);
}

Fără prototipul din primul rând, programul nu se compilează.

În Python

Nu se declară nimic înainte. Numele se caută în momentul apelului, nu în momentul citirii programului, deci par se poate scrie prima chiar dacă folosește impar.

def par(n):
    if n == 0:
        return True
    else:
        return impar(n - 1)

def impar(n):
    if n == 0:
        return False
    else:
        return par(n - 1)

Trebuie doar ca amândouă să fie definite înainte de primul apel, nu înainte una de alta.

Mecanismul recursivității

Pe segmentul de stivă se păstrează, la fiecare apel:

  • variabilele locale ale subprogramului;
  • parametrii formali, adică valorile sau referințele transmise la apel;
  • adresa de revenire, adică locul din program unde execuția se întoarce după ce subprogramul se încheie.

Ce se întâmplă la fiecare apel

PasulCe se execută
Pas 1. La primul apelSe depun pe primul nivel al segmentului de stivă parametrii transmiși, în ordine, și se rezervă spațiu pentru variabilele locale.
Pas 2. La autoapelSe depun pe al doilea nivel, din nou, parametrii transmiși, și se rezervă spațiu nou pentru variabilele locale.
Pas 3. La revenireVârful stivei coboară și este adus la valoarea dinaintea activării.

De câte ori se autoapelează subprogramul, se creează un nivel nou. Așa se explică de ce toate activările lui se află deodată în stivă.

Fiecare autoapel primește o zonă nouă de memorie, deci și o definire nouă a variabilelor locale: variabila locală este unică pentru un apel. Dacă subprogramul se apelează recursiv de n ori, există n imagini ale aceleiași variabile, câte una pentru fiecare apel, fiecare cu conținutul ei.

La calculul lui 5! sunt 6 apeluri: pentru 5, 4, 3, 2, 1 și 0.

Subprogram-funcție: factorialul

Un subprogram-funcție recursiv întoarce o valoare prin return. Factorialul se calculează după formula:

factorial(x) = 1,                       dacă x = 0
factorial(x) = x · factorial(x − 1),    dacă x ≥ 1

În C++

long long factorial(int x) {
    if (x == 0)
        return 1;               // conditia de oprire
    else
        return x * factorial(x - 1);   // autoapelul
}

int main() {
    int n;
    cin >> n;
    cout << "Factorial " << factorial(n);
    return 0;
}

În Python

def factorial(x):
    if x == 0:
        return 1                       # conditia de oprire
    else:
        return x * factorial(x - 1)    # autoapelul

n = int(input())
print('Factorial', factorial(n))

Nu se pune problema depășirii domeniului: int nu are limită de mărime, iar factorial(50) se calculează exact, cu toate cele 65 de cifre.

Evoluția parametrului la coborâre și la revenire

La coborâre se rețin pe fiecare nivel valorile 5, 4, 3, 2, 1, 0. Înmulțirile se fac abia la revenire, de la baza stivei spre vârf:

NivelulCe se calculeazăRezultatul
x = 0condiția de oprire1
x = 11 · factorial(0)1
x = 22 · factorial(1)2
x = 33 · factorial(2)6
x = 44 · factorial(3)24
x = 55 · factorial(4)120

Desfășurat, calculul arată așa:

factorial(5) = 5 · factorial(4)
             = 5 · 4 · factorial(3)
             = 5 · 4 · 3 · factorial(2)
             = 5 · 4 · 3 · 2 · factorial(1)
             = 5 · 4 · 3 · 2 · 1 · factorial(0)
             = 5 · 4 · 3 · 2 · 1 · 1 = 120

Niciun rezultat nu se obține la coborâre. Toate se obțin la revenire, iar valoarea este întoarsă prin return din apel în apel, până la programul principal.

Subprogram-procedură: afișarea cifrelor

Un subprogram-procedură recursiv nu întoarce nimic; el afișează. Aici nu mai contează valoarea întoarsă prin return, ci unde este scrisă afișarea față de autoapel.

În C++

void cifre(int n) {
    if (n > 9)
        cifre(n / 10);
    cout << n % 10 << " ";
}

int main() {
    cifre(357);
    return 0;
}

În Python

def cifre(n):
    if n > 9:
        cifre(n // 10)
    print(n % 10, end=' ')

cifre(357)

Împărțirea se scrie //, nu /. Cu /, parametrii autoapelurilor ar fi numerele reale 35.7 și 3.57. Programul s-ar încheia, dar ar afișa valori reale în locul cifrelor: 3.5700000000000003 5.700000000000003 7. Nu există void: un subprogram care nu are return întoarce None.

Evoluția parametrului

Fiecare apel are copia lui de n. La coborâre se rețin, prin împărțiri succesive la 10, valorile 357, 35, 3. La revenire, fiecare nivel afișează n % 10 din copia lui:

NivelulnCe face
1357357 > 9, deci se autoapelează cu 35
23535 > 9, deci se autoapelează cu 3
333 > 9 este fals, deci afișează 3
revine la 235afișează 5
revine la 1357afișează 7

Se afișează 3 5 7, adică cifrele în ordinea firească, deși împărțirile le-au dat de la ultima spre prima. Ordinea se inversează fiindcă afișarea este scrisă după autoapel. Mutată înaintea lui, s-ar afișa 7 5 3.

Materialul acesta se citește pe educamp.ro și nu se tipărește.

Ce cuprinde subcapitolul

  1. Recursivitate directă și indirectă
  2. Mecanismul recursivității
  3. Subprogram-funcție: factorialul
  4. Subprogram-procedură: afișarea cifrelor
  5. Funcție sau procedură
  6. Alte exemple
  7. Avantaje și dezavantaje
  8. Apariții la examen

Continuă lectura ca și cursant

Cel puțin un subcapitol din fiecare capitol este disponibil gratuit și integral. Pentru a citi toate celelalte subcapitole ale disciplinei, te înscrii la cursul de pregătire.

Te înscrii, alegi în cont când începe cursul și plătești prima lună prin transfer bancar. Pentru a vedea mai întâi cum este prezentată materia, poți reveni la primul subcapitol al capitolului.

Acces la suportul de curs

25 RON / lună, fără ședințe

Ce cuprinde:

  • Acces la toate lecțiile disponibile
  • Suport de curs pentru tematica științifică și metodică
  • Exemple, explicații și exerciții
  • Acces la materialele noi adăugate pe platformă
  • Posibilitatea de a adresa întrebări

Poți alege și variante cu ședințe online, în grup sau individuale. Le vezi pe pagina cursului.

Ai întrebări sau o problemă? Scrie-mi pe WhatsApp, la 0745 874 576.

Înscrie-te Alte varianteCum plătești Login

Surse (3)
  • Cerchez, E., Șerban, M., „Programarea în limbajul C/C++ pentru liceu”, Editura Polirom, Iași, 2005
  • „Informatică. Manual pentru clasa a XI-a”, Editura Didactică și Pedagogică, București
  • „Tutorialul de Python”, documentația oficială a limbajului Python, https://docs.python.org/ro/3/tutorial/index.html
Actualizat: 20 octombrie 2026