Sari la conținut

Capitolul 11 · Lecția 11.1 din 2

Recursivitate: funcții care se autoapelează

Mecanismul recursivității, cazul de bază, exemple clasice și urmărirea apelurilor.

Capitolul 11: RecursivitateConținut verificat

Pe scurt pentru BAC · 5 idei

  • O funcție este recursivă dacă se apelează pe ea însăși, ca factorialul definit prin n!=n⋅(n−1)!n! = n \cdot (n-1)! și 0!=10! = 1.
  • Suma cifrelor recursivă întoarce n % 10 + sc(n / 10), iar cazul de bază n == 0 întoarce 0.
  • Algoritmul lui Euclid recursiv întoarce a când b == 0, altfel apelează cmmdc(b, a % b).
  • Ca să urmărești un apel, scrii fiecare apel pe un rând, cobori până la cazul de bază, apoi urci înlocuind apelurile cu valorile returnate.
  • Fără caz de bază sau cu un autoapel care nu micșorează problema, funcția se apelează la infinit (stack overflow).
Pe această pagină5 secțiuni

Ce este recursivitatea

O funcție este recursivă dacă se apelează pe ea însăși. Orice funcție recursivă corectă are:

  1. cazul de bază: condiția de oprire, fără autoapel;
  2. cazul general: autoapelul pe o problemă MAI MICĂ.

Exemplul fundamental: factorialul

n!=n⋅(n−1)!0!=1n! = n \cdot (n-1)! \qquad 0! = 1

Factorialul, recursiv

#include <iostream>
using namespace std;

int fact(int n) {
    if (n == 0) return 1;
    return n * fact(n - 1);
}

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

Atenție: In Pascal rezultatul functiei se atribuie numelui ei, nu se scrie return. Aici fact e longint, fiindca factorialul creste foarte repede.

se trimit programului la citire

Urmărirea pentru fact(4): 4⋅fact(3)=4⋅3⋅fact(2)=4⋅3⋅2⋅fact(1)=4⋅3⋅2⋅1⋅fact(0)=244 \cdot fact(3) = 4 \cdot 3 \cdot fact(2) = 4 \cdot 3 \cdot 2 \cdot fact(1) = 4 \cdot 3 \cdot 2 \cdot 1 \cdot fact(0) = 24.

Alte exemple clasice

Suma cifrelor:

Suma cifrelor, recursiv

#include <iostream>
using namespace std;

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

int main() {
    cout << sc(4729);
    return 0;
}

Atenție: Impartirea intreaga se scrie / in C si C++ pentru intregi, div in Pascal si // in Python. Cu / simplu, Python ar da un numar zecimal si recursivitatea nu s-ar opri.

se trimit programului la citire

sc(275) = 5 + sc(27) = 5 + 7 + sc(2) = 5 + 7 + 2 + sc(0) = 14.

Cel mai mare divizor comun (Euclid):

Cel mai mare divizor comun, recursiv

#include <iostream>
using namespace std;

int cmmdc(int a, int b) {
    if (b == 0) return a;
    return cmmdc(b, a % b);
}

int main() {
    cout << cmmdc(48, 18);
    return 0;
}
se trimit programului la citire

cmmdc(24, 36) = cmmdc(36, 24) = cmmdc(24, 12) = cmmdc(12, 0) = 12.

Cum urmărești un apel la BAC

  1. Scrie fiecare apel pe un rând, cu argumentele lui.
  2. Coboară până la cazul de bază.
  3. Urcă înapoi înlocuind fiecare apel cu valoarea returnată.

Atenție

Fără caz de bază (sau cu autoapel care NU micșorează problema), funcția se apelează la infinit: stack overflow. La subiectele de tip "ce afișează", verifică întâi condiția de oprire.

Reține

Orice funcție recursivă are un caz de bază (oprire, fără autoapel) și un caz general (autoapel pe o problemă mai mică). Valori de verificare: fact(0) = 1, sc(275) = 14, cmmdc(24, 36) = 12.

Greșeli frecvente

  1. Ordinea contează: return n * fact(n-1) înmulțește DUPĂ întoarcerea din apel.
  2. La afișări recursive, instrucțiunile de DINAINTE de autoapel se execută la coborâre, cele de DUPĂ la întoarcere: de aici apar afișările "inversate".
  3. fact(0) este 1, nu 0.

Instrumente pentru lecția asta

Stiva apelurilor recursive

Factorial, sumă și Fibonacci pas cu pas: vezi fiecare apel cum intră în stivă, așteaptă și întoarce valoarea, cu codul alături.

Se încarcă instrumentul…

Bifează când ai terminat, ca s-o vezi citită pe toate dispozitivele.

Testează-te pe capitolul 11

Lecția în clipuri

Clipuri scurte, cu voce și subtitrări.

Folosim cookie-uri esențiale, fără de care site-ul nu merge, și cookie-uri de analiză anonimizate, ca să vedem ce pagini ajută. Detalii în politica de confidențialitate