|

Structuri de Date Arborescente Implementate Dinamic – Arbori Binari 14


1. Obiectivele lecției:

  • Să înțeleagă conceptul de arbore binar și proprietățile acestuia.
  • Să învețe cum să implementeze un arbore binar dinamic.
  • Să implementeze operații comune pe arbori binari: inserare, căutare, traversare (în ordine, preordine, postordine).

2. Ce este un arbore binar?

  1. Definiție:
    Un arbore binar este o structură de date arborescentă în care fiecare nod are cel mult doi copii:
    • Subarborele stâng
    • Subarborele drept
  2. Proprietăți:
    • Arborele binar poate fi complet, perfect sau degenerat.
    • Într-un arbore binar, numărul maxim de noduri la nivelul hhh este 2h2^h2h.
    • Înălțimea arborelui este dată de lungimea drumului de la rădăcină la cea mai adâncă frunză.
  3. Tipuri de arbori binari:
    • Arbore binar complet: Fiecare nivel, cu excepția ultimului, este complet populat.
    • Arbore binar de căutare (BST): Subarborele stâng conține valori mai mici, iar subarborele drept conține valori mai mari decât rădăcina.

3. Avantaje și dezavantaje

AvantajeDezavantaje
Structură flexibilă pentru gestionarea datelor ierarhice.Gestionarea dinamică necesită atenție pentru integritate.
Traversare eficientă pentru căutare, inserare și ștergere.Performanța poate scădea în cazuri de arbori dezechilibrați.
Este baza pentru alte structuri complexe, cum ar fi heap-uri.

4. Structura unui nod

struct Nod {

    int valoare;       // Valoarea stocată în nod

    Nod* stanga;       // Pointer către subarborele stâng

    Nod* dreapta;      // Pointer către subarborele drept

};


5. Operații comune pe arbori binari


1. Crearea unui nod

Nod* creeazaNod(int valoare) {

    Nod* nod = new Nod();

    nod->valoare = valoare;

    nod->stanga = nullptr;

    nod->dreapta = nullptr;

    return nod;

}


2. Inserarea unui nod într-un arbore binar de căutare (BST)

Nod* insereazaNod(Nod* radacina, int valoare) {

    if (radacina == nullptr) {

        return creeazaNod(valoare);

    }

    if (valoare < radacina->valoare) {

        radacina->stanga = insereazaNod(radacina->stanga, valoare);

    } else if (valoare > radacina->valoare) {

        radacina->dreapta = insereazaNod(radacina->dreapta, valoare);

    }

    return radacina;

}


3. Traversări ale arborelui

  1. Traversare în ordine (in-order):
    Vizitează nodurile în ordinea: stânga → rădăcină → dreapta.

void traversareInOrdine(Nod* radacina) {

    if (radacina == nullptr) return;

    traversareInOrdine(radacina->stanga);

    cout << radacina->valoare << ” „;

    traversareInOrdine(radacina->dreapta);

}

  1. Traversare preordine (pre-order):
    Vizitează nodurile în ordinea: rădăcină → stânga → dreapta.

void traversarePreOrdine(Nod* radacina) {

    if (radacina == nullptr) return;

    cout << radacina->valoare << ” „;

    traversarePreOrdine(radacina->stanga);

    traversarePreOrdine(radacina->dreapta);

}

  1. Traversare postordine (post-order):
    Vizitează nodurile în ordinea: stânga → dreapta → rădăcină.

void traversarePostOrdine(Nod* radacina) {

    if (radacina == nullptr) return;

    traversarePostOrdine(radacina->stanga);

    traversarePostOrdine(radacina->dreapta);

    cout << radacina->valoare << ” „;

}


4. Căutarea unui element

bool cautaValoare(Nod* radacina, int valoare) {

    if (radacina == nullptr) {

        return false;

    }

    if (valoare == radacina->valoare) {

        return true;

    } else if (valoare < radacina->valoare) {

        return cautaValoare(radacina->stanga, valoare);

    } else {

        return cautaValoare(radacina->dreapta, valoare);

    }

}


5. Ștergerea unui nod

Nod* stergeNod(Nod* radacina, int valoare) {

    if (radacina == nullptr) return radacina;

    if (valoare < radacina->valoare) {

        radacina->stanga = stergeNod(radacina->stanga, valoare);

    } else if (valoare > radacina->valoare) {

        radacina->dreapta = stergeNod(radacina->dreapta, valoare);

    } else {

        if (radacina->stanga == nullptr) {

            Nod* temp = radacina->dreapta;

            delete radacina;

            return temp;

        } else if (radacina->dreapta == nullptr) {

            Nod* temp = radacina->stanga;

            delete radacina;

            return temp;

        }

        Nod* temp = radacina->dreapta;

        while (temp->stanga != nullptr) {

            temp = temp->stanga;

        }

        radacina->valoare = temp->valoare;

        radacina->dreapta = stergeNod(radacina->dreapta, temp->valoare);

    }

    return radacina;

}


6. Exemplu complet

#include <iostream>

using namespace std;

struct Nod {

    int valoare;

    Nod* stanga;

    Nod* dreapta;

};

Nod* creeazaNod(int valoare) {

    Nod* nod = new Nod();

    nod->valoare = valoare;

    nod->stanga = nullptr;

    nod->dreapta = nullptr;

    return nod;

}

Nod* insereazaNod(Nod* radacina, int valoare) {

    if (radacina == nullptr) {

        return creeazaNod(valoare);

    }

    if (valoare < radacina->valoare) {

        radacina->stanga = insereazaNod(radacina->stanga, valoare);

    } else if (valoare > radacina->valoare) {

        radacina->dreapta = insereazaNod(radacina->dreapta, valoare);

    }

    return radacina;

}

void traversareInOrdine(Nod* radacina) {

    if (radacina == nullptr) return;

    traversareInOrdine(radacina->stanga);

    cout << radacina->valoare << ” „;

    traversareInOrdine(radacina->dreapta);

}

int main() {

    Nod* radacina = nullptr;

    radacina = insereazaNod(radacina, 50);

    insereazaNod(radacina, 30);

    insereazaNod(radacina, 70);

    insereazaNod(radacina, 20);

    insereazaNod(radacina, 40);

    insereazaNod(radacina, 60);

    insereazaNod(radacina, 80);

    cout << „Traversare în ordine: „;

    traversareInOrdine(radacina);

    cout << endl;

    return 0;

}


6. Activități practice pentru elevi

  1. Implementați o funcție care calculează înălțimea unui arbore binar.
  2. Scrieți un program care determină dacă un arbore este echilibrat.
  3. Implementați o funcție pentru numărarea nodurilor frunză dintr-un arbore binar.

7. Scheme logice

  1. Inserare:
    • Verifică dacă nodul curent este gol -> Creează un nou nod -> Compară valoarea și inserează în stânga sau dreapta.
  2. Traversare:
    • Utilizează recursivitate pentru a parcurge nodurile în ordinea specificată.
  3. Căutare:
    • Compară valoarea căutată cu nodul curent -> Explorează subarborele corespunzător.

8. Concluzie

  • Arborii binari sunt structuri de date versatile utilizate în multe aplicații informatice.
  • Implementarea dinamică permite gestionarea eficientă a memoriei și flexibilitatea dimensiunii arborelui.

Similar Posts

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *