Middle
Jak je v kontejneru unordered_map strukturována hash tabulka?
sobes.tech AI
Odpověď od AI
unordered_map v C++ je implementován jako hash tabulka.
Princip fungování:
- Hashování: Klíč je převeden na celé číslo — hash kód — pomocí hashovací funkce.
- Indexace: Hash kód se používá k určení indexu (kontejner nebo bucket) v poli ukazatelů nebo seznamů.
- Uložení: V každém bucketu jsou uloženy páry klíč-hodnota.
Vlastnosti:
- Bucket: Hash tabulka se skládá z pole bucketů. Počet bucketů se může dynamicky měnit (rehashování), když je dosažen určitý faktor zatížení.
- Kolize: Různé klíče mohou dávat stejný hash kód. To se nazývá kolize. Pro řešení kolizí se v
unordered_mappoužívá metoda ** chaining **: prvky se stejným hashem jsou přidávány do spojovaného seznamu (nebo jiné datové struktury) v příslušném bucketu. - Hashovací funkce a funkce porovnání: Pro správnou funkci jsou potřeba dvě věci:
- Dobrá hashovací funkce, která rovnoměrně rozděluje klíče mezi buckety, minimalizuje kolize.
- Operátor
==pro rozlišení klíčů se stejným hashem v jednom bucketu.
- Výkon: Průměrně mají operace vkládání, mazání a hledání časovou složitost O(1). V nejhorším případě (například při velkém počtu kolizí nebo špatně zvolené hashovací funkci) může výkon klesnout na O(n), kde n je počet prvků.
Příklad struktury (zjednodušené):
struct Node {
KeyType key;
ValueType value;
Node* next; // Pro spojovaný seznam v bucketu
};
struct Bucket {
Node* head; // Ukazatel na začátek seznamu
};
Bucket* buckets; // Pole bucketů
size_t num_buckets;
Proces přidání prvku:
- Vypočítá se hash kód klíče.
- Určí se index bucketu:
bucket_index = hash(key) % num_buckets. - Pár klíč-hodnota se přidá do seznamu prvků v tomto bucketu. Pokud klíč již existuje, aktualizuje se hodnota.
Proces hledání prvku:
- Vypočítá se hash kód klíče.
- Určí se index bucketu.
- Prochází se seznam prvků v tomto bucketu, porovnávají se klíče s hledaným pomocí operátoru
==.
Rehashing nastává, když počet prvků v poměru k počtu bucketů překročí práh (faktor zatížení). Během rehashingu se vytvoří nový, větší pole bucketů a všechny prvky ze starých bucketů jsou znovu hashovány a přesunuty do nových.