Video: Recursivitate în C++

Recursivitate în C++

Să ne gândim la un copac: acesta are ramuri, fiecare ramură având la rândul ei mai multe ramuri mai mici, și așa mai departe până la cele mai mici ramuri.

https://i.ibb.co/k4V2q3h/image.png

În matematică și în informatică întâlnim o noțiune similară, numită recursivitate (sau recurență), de a defini ceva cu ea însăși.

Vom folosi funcții în această lecție — altfel, nu am putea să folosim recursivitatea.

Definiția recursivității

Recursivitatea este proprietatea unui element de a se defini prin el însuși.

Exemple

Noțiunea de recursivitate poate părea destul de dificil de înțeles, așadar să considerăm câteva exemple.

Exemple în matematică

Factorialul unui număr n, n!, este egal cu produsul 1 × 2 × 3 × … × (n - 1) × n. Putem să rescriem factorialul astfel: n! = (n - 1)! × n. Astfel, am definit factorialul lui n pe baza factorialului lui n - 1.

Șirul Fibonacci este un șir cunoscut în matematică, cu primii doi termeni 1 și 1, iar termenul F(n) = F(n - 1) + F(n - 2).

Progresiile aritmetice și geometrice se pot scrie recursiv: `a(n) = a(n -

    • r, sau g(n) = g(n - 1) * r`.

Exemple vizuale

Fractalii sunt un exemplu bun de recursivitate, în care nu există vreo limită de oprire (spre deosebire de șirul Fibonacci, spre exemplu, unde avem limita n = 1 sau n = 2). Iată un fractal în formă de pătrat, în care colțul din stânga sus este identic cu tot pătratul:

https://i.ibb.co/bbg1J7N/image.png

Un alt fractal — triunghiul Sierpinski. Triunghiul se împarte în 4 triunghiuri egale, iar în cele 3 din colțuri se repetă fractalul.

https://i.ibb.co/zVVjSc8/image.png

Un ultim exemplu este efectul Droste: un ambalaj care se conține pe el însuși:

https://i.ibb.co/XYg7PMN/image.png

Implementarea unei funcții recursive în C++

Să zicem că vrem să calculăm factorialul unui număr. Metoda clasică este următoarea:

#include <iostream>

using namespace std;

int factorial(int n) {
    int fact = 1;
    for(int i = 1; i <= n; i++) {
        fact *= i;
    }
    return fact;
}

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

Dacă am implementa recursiv soluția la această problemă, am crea o funcție care se definește pe ea însăși în apel:

#include <iostream>

using namespace std;

int factorial(int n) {
    if(n <= 0) { //Caz particular
        return 1;
    } else { //Formula generală
        return n * factorial(n - 1);
    }
}

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

Cum funcționează recursivitatea? (animație)

Iată o reprezentare pentru apelarea factorial(4):

Variabilă / Expresie Valoare
factorial(4) ???4 * factorial(3)62424
factorial(3) ???3 * factorial(2)266
factorial(2) ???2 * factorial(1)122
factorial(1) ???1 * factorial(0)111
factorial(0) ???11

Avantajele și dezavantajele recursivității

Avantaj: mod nou de gândire

Recursivitatea aduce o nouă metodă de a vizualiza problemele. Această metodă, de a împărți problema curentă în probleme mai mici, până când ajungem la probleme simple și rezolvabile instant, va fi mai târziu (în clasa a XI-a) folosită la programarea dinamică.

Avantaj: anumite probleme nu se pot implementa decât recursiv

Unele probleme sunt foarte greu — sau chiar imposibil — implementabile nerecursiv. În clasa a XI-a se vor folosi funcțiile recursive pentru backtracking.

Dezavantaj: programele sunt foarte încete

Soluțiile recursive, fără optimizări, pot lua mai mult timp să ruleze, astfel că implementările recursive nu sunt foarte utile în programe în care viteza este importantă. Cu toate acestea, de obicei acest lucru nu reprezintă un pericol.

Dezavantaj: multe funcții se pot implementa nerecursiv

După cum s-a observat și anterior, majoritatea noțiunilor pe care le putem implementa recursiv (Fibonacci, progresii aritmetice sau geometrice, factorialul, etc.) s-au implementat deja nerecursiv. Așadar, nu are sens să reinventăm roata.

Exerciții propuse

Completează următoarele secvențe de cod:

Să se determine recursiv al n-lea termen tribonacci (elementul curent este egal cu suma ultimelor trei):

int tribo(int x) {
    if(x <= 3) {
        return 1;
    }
    ??? tribo(x - 1) + tribo(x - ???) + tribo(x - 3);
}

Să se afișeze crescător primele n numere naturale:

void f(int n) {
    if(n > 1) {
        ???(n - 1);
    }
    cout << ??? << " ";
}

Alte resurse și bibliografie

DS

Autorul acestei lecții

Dominic Satnoianu

Această lecție a fost redactată de către Dominic Satnoianu.

© 2021 – 2025 Aspire Education Labs SRL. Toate drepturile rezervate.

Așa cum este specificat și în termeni și condiții, conținutul acestei pagini este protejat de legea drepturilor de autor și este interzisă copierea sau modificarea acestuia fără acordul scris al autorilor.

Încălcarea drepturilor de autor este o infracțiune și se pedepsește conform legii.

Comentarii 0

Autentifică-te pentru a putea comenta.

Autentifică-te