Middle
Cum este structurată o tabelă hash în containerul unordered_map?
sobes.tech AI
Răspuns de la AI
unordered_map în C++ este implementat ca un tabel hash.
Principiul de funcționare:
- Hashing: Cheia este transformată într-un număr întreg — cod hash — folosind o funcție hash.
- Indexare: Codul hash este folosit pentru a determina indexul (găleată sau bucket) într-un array de pointeri sau liste.
- Stocare: În fiecare găleată se stochează perechi cheie-valoare.
Caracteristici:
- Găleți: Tabelul hash constă dintr-un array de găleți. Numărul de găleți poate fi modificat dinamic (rehashing) atunci când se atinge un anumit factor de încărcare.
- Coliziuni: Chei diferite pot da același cod hash. Acest lucru se numește coliziune. Pentru rezolvarea coliziunilor,
unordered_mapfolosește metoda ** chaining **: elementele cu același hash sunt adăugate într-o listă legată (sau altă structură de date) în găleata corespunzătoare. - Funcție hash și funcție de comparație: Pentru funcționare corectă sunt necesare două lucruri:
- O funcție hash bună, care distribuie uniform cheile între găleți, minimizând coliziunile.
- O funcție de egalitate (
==), pentru a distinge cheile cu același cod hash în aceeași găleată.
- Performanță: În medie, operațiile de inserare, ștergere și căutare au complexitate temporară O(1). În cel mai rău caz (de exemplu, multe coliziuni sau o funcție hash prost aleasă), performanța poate scădea la O(n), unde n este numărul de elemente.
Exemplu de structură (simplificat):
struct Node {
KeyType key;
ValueType value;
Node* next; // Pentru listă legată în găleată
};
struct Bucket {
Node* head; // Pionier la începutul listei
};
Bucket* buckets; // Array de găleți
size_t num_buckets;
Procesul de adăugare a unui element:
- Se calculează codul hash al cheii.
- Se determină indexul găleții:
bucket_index = hash(key) % num_buckets. - Partea cheie-valoare este adăugată în lista de elemente din acea găleată. Dacă cheia există deja, valoarea se actualizează.
Procesul de căutare a unui element:
- Se calculează codul hash al cheii.
- Se determină indexul găleții.
- Se parcurge lista de elemente din acea găleată, comparând cheile cu cea căutată folosind operatorul
==.
Rehashing-ul are loc atunci când numărul de elemente în raport cu numărul de găleți depășește un prag (factor de încărcare). În timpul rehashing-ului, se creează un nou array de găleți mai mare, iar toate elementele din gălețile vechi sunt re-hash-uite și mutate în cele noi.