|

Structuri de Date Arborescente Implementate Dinamic – Arbore Binar Heap 15


1. Obiectivele lecției:

  • Să înțeleagă conceptul de heap și proprietățile acestuia.
  • Să învețe cum să implementeze un heap binar.
  • Să implementeze operații comune pe heap: inserare, eliminare, max-heapify/min-heapify.

2. Ce este un heap binar?

  1. Definiție:
    Un heap binar este un arbore binar complet care respectă una dintre următoarele proprietăți:
    • Max-Heap: Valoarea oricărui nod este mai mare sau egală decât valorile copiilor săi.
    • Min-Heap: Valoarea oricărui nod este mai mică sau egală decât valorile copiilor săi.
  2. Proprietăți:
    • Este un arbore complet (toate nivelurile, cu excepția ultimului, sunt complet populate).
    • Este utilizat frecvent pentru implementarea cozilor de priorități.

3. Avantaje și dezavantaje

AvantajeDezavantaje
Eficient pentru accesarea elementelor de maxim/minim.Inserarea și eliminarea implică reorganizarea arborelui.
Structura este compactă datorită proprietății de arbore complet.Performanța scade dacă arborele devine dezechilibrat.
Util pentru aplicații precum algoritmii de sortare și cozi de priorități.

4. Reprezentarea unui heap

Heap-urile sunt reprezentate în mod obișnuit folosind:

  1. Vectori: Copilul stâng și copilul drept ale unui nod se află la pozițiile 2i+12i + 12i+1 și 2i+22i + 22i+2, respectiv.
  2. Structuri dinamice: Fiecare nod are pointeri către copiii săi.

5. Structura unui nod pentru un heap

struct Nod {

    int valoare;

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

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

};


6. Implementarea unui Max-Heap

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 element în heap

Inserarea se face astfel:

  1. Adăugăm elementul într-un loc valid (pentru a păstra proprietatea de arbore complet).
  2. Reorganizăm arborele pentru a menține proprietatea de heap (numită heapify-up).

void heapifyUp(vector<int>& heap, int index) {

    int parinte = (index – 1) / 2;

    while (index > 0 && heap[index] > heap[parinte]) {

        swap(heap[index], heap[parinte]);

        index = parinte;

        parinte = (index – 1) / 2;

    }

}

void inserare(vector<int>& heap, int valoare) {

    heap.push_back(valoare); // Adăugăm elementul la final

    heapifyUp(heap, heap.size() – 1); // Reorganizăm arborele

}


3. Eliminarea elementului maxim

Eliminarea elementului maxim (rădăcina) implică:

  1. Înlocuirea rădăcinii cu ultimul element.
  2. Eliminarea ultimului element.
  3. Reorganizarea arborelui pentru a menține proprietatea de heap (numită heapify-down).

void heapifyDown(vector<int>& heap, int index) {

    int stanga = 2 * index + 1;

    int dreapta = 2 * index + 2;

    int celMaiMare = index;

    if (stanga < heap.size() && heap[stanga] > heap[celMaiMare]) {

        celMaiMare = stanga;

    }

    if (dreapta < heap.size() && heap[dreapta] > heap[celMaiMare]) {

        celMaiMare = dreapta;

    }

    if (celMaiMare != index) {

        swap(heap[index], heap[celMaiMare]);

        heapifyDown(heap, celMaiMare);

    }

}

void eliminareMax(vector<int>& heap) {

    if (heap.empty()) {

        cout << „Heap-ul este gol.” << endl;

        return;

    }

    heap[0] = heap.back(); // Înlocuim rădăcina cu ultimul element

    heap.pop_back(); // Eliminăm ultimul element

    heapifyDown(heap, 0); // Reorganizăm arborele

}


4. Afișarea elementelor din heap

void afisareHeap(const vector<int>& heap) {

    for (int valoare : heap) {

        cout << valoare << ” „;

    }

    cout << endl;

}


7. Exemplu complet pentru Max-Heap

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

void heapifyUp(vector<int>& heap, int index) {

    int parinte = (index – 1) / 2;

    while (index > 0 && heap[index] > heap[parinte]) {

        swap(heap[index], heap[parinte]);

        index = parinte;

        parinte = (index – 1) / 2;

    }

}

void inserare(vector<int>& heap, int valoare) {

    heap.push_back(valoare); // Adăugăm elementul la final

    heapifyUp(heap, heap.size() – 1); // Reorganizăm arborele

}

void heapifyDown(vector<int>& heap, int index) {

    int stanga = 2 * index + 1;

    int dreapta = 2 * index + 2;

    int celMaiMare = index;

    if (stanga < heap.size() && heap[stanga] > heap[celMaiMare]) {

        celMaiMare = stanga;

    }

    if (dreapta < heap.size() && heap[dreapta] > heap[celMaiMare]) {

        celMaiMare = dreapta;

    }

    if (celMaiMare != index) {

        swap(heap[index], heap[celMaiMare]);

        heapifyDown(heap, celMaiMare);

    }

}

void eliminareMax(vector<int>& heap) {

    if (heap.empty()) {

        cout << „Heap-ul este gol.” << endl;

        return;

    }

    heap[0] = heap.back(); // Înlocuim rădăcina cu ultimul element

    heap.pop_back(); // Eliminăm ultimul element

    heapifyDown(heap, 0); // Reorganizăm arborele

}

void afisareHeap(const vector<int>& heap) {

    for (int valoare : heap) {

        cout << valoare << ” „;

    }

    cout << endl;

}

int main() {

    vector<int> heap;

    inserare(heap, 10);

    inserare(heap, 20);

    inserare(heap, 15);

    inserare(heap, 30);

    inserare(heap, 40);

    cout << „Heap după inserări: „;

    afisareHeap(heap);

    eliminareMax(heap);

    cout << „Heap după eliminarea maximului: „;

    afisareHeap(heap);

    return 0;

}


8. Activități practice pentru elevi

  1. Implementați un Min-Heap folosind aceleași metode, modificând condițiile din funcțiile heapifyUp și heapifyDown.
  2. Scrieți o funcție care sortează un vector utilizând algoritmul Heap Sort.
  3. Realizați o aplicație care implementează o coadă de priorități utilizând un heap.

9. Scheme logice

  1. Inserare:
    • Adăugăm elementul la sfârșitul arborelui -> Reorganizăm pentru a menține proprietatea de heap.
  2. Eliminare:
    • Înlocuim rădăcina cu ultimul element -> Eliminăm ultimul element -> Reorganizăm arborele.

10. Concluzie

  • Heap-urile binare sunt structuri esențiale pentru optimizarea accesului la valorile maxime sau minime.
  • Implementarea dinamică permite gestionarea eficientă a resurselor.
  • Practica este cheia pentru a înțelege și aplica aceste structuri în probleme complexe.

Similar Posts

Lasă un răspuns

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