Menu
Coddy logo textTech

Hash map

Ultimo aggiornamento

Una hash map memorizza coppie chiave-valore e ti permette di trovare un valore tramite la sua chiave in O(1) in media. Funziona esattamente come una tabella hash, ma ogni voce di un bucket contiene sia una chiave sia il valore associato. Per salvare o recuperare una coppia, la chiave viene trasformata con l'hash in un indice di bucket, poi la catena del bucket viene scorsa alla ricerca della chiave corrispondente. Premi play qui sopra per vedere le coppie collocate nel bucket calcolato con l'hash e un valore recuperato tramite la sua chiave.

È la struttura dietro il dict di Python, la HashMap di Java e Map/gli oggetti di JavaScript. Le collisioni si gestiscono come in una tabella hash, qui con il concatenamento separato, quindi le prestazioni dipendono da una buona funzione di hash e da un fattore di carico basso.

Complessità temporale

OperazioneMediaCaso peggiore
Put (inserimento/aggiornamento)O(1)O(n)
Get (ricerca)O(1)O(n)
EliminazioneO(1)O(n)
SpazioO(n)O(n)

La hash map nei linguaggi più comuni

LinguaggioTipo
Pythondict
JavaHashMap
JavaScriptMap / oggetto
C++std::unordered_map
Gomap

Esempio svolto

Inserimento delle coppie ("cat", 3), ("dog", 5), ("cat", 9), ("emu", 7) in una mappa con 8 bucket, usando hash(key) % 8. Supponiamo che hash("cat") % 8 = 2, hash("dog") % 8 = 5, hash("emu") % 8 = 2:

PassoStrutturaAzione
Put ("cat", 3)bucket 2: [("cat", 3)]L'hash porta al bucket 2; catena vuota, quindi aggiungi la coppia.
Put ("dog", 5)bucket 2: [("cat", 3)], bucket 5: [("dog", 5)]L'hash porta al bucket 5; catena vuota, quindi aggiungi la coppia.
Put ("cat", 9)bucket 2: [("cat", 9)], bucket 5: [("dog", 5)]L'hash porta al bucket 2; la chiave "cat" è già nella catena, quindi aggiorna il suo valore a 9.
Put ("emu", 7)bucket 2: [("cat", 9), ("emu", 7)], bucket 5: [("dog", 5)]L'hash porta al bucket 2; collide con "cat", la chiave non c'è, quindi aggiungi la coppia.
Get "emu"bucket 2: [("cat", 9), ("emu", 7)]L'hash porta al bucket 2; scorri la catena, salta "cat", trova "emu", restituisci 7.

Quando usare una hash map

Usala quandoEvitala quando
Ti servono ricerca, inserimento ed eliminazione O(1) in media tramite una chiave esatta.Ti servono chiavi in ordine o query su intervalli: usa un BST bilanciato o una mappa ordinata.
Le chiavi sono hashable e l'uguaglianza è ben definita (stringhe, interi, tuple).Le chiavi sono mutabili e possono cambiare dopo l'inserimento, corrompendo il loro bucket.
Stai contando, eliminando duplicati, facendo caching o indicizzando per identificatore.Ti servono garanzie O(log n) nel caso peggiore invece di limiti medi ammortizzati.
L'ordine di iterazione non conta, oppure basta una mappa che conserva l'ordine di inserimento.La memoria è molto limitata: bucket, margine per il fattore di carico e puntatori aggiungono overhead.

Codice Hash Map

Un'implementazione di Hash Map pulita ed eseguibile in Python, JavaScript, Java, C++, C. Scegli un linguaggio, copia il codice o aprilo già caricato nel Playground di Coddy.

Codice Hash Map in Python

Python
1# Python's built-in dict is a hash map: O(1) average2# insert, lookup, and delete.3inventory = {"apple": 3, "banana": 7}4
5# Insert and update6inventory["cherry"] = 57inventory["apple"] += 28
9# Lookup, with .get for a safe default on missing keys10print("apple: ", inventory["apple"])11print("mango: ", inventory.get("mango", 0))12
13# Membership test and delete14print("banana in stock:", "banana" in inventory)15del inventory["banana"]16print("banana in stock:", "banana" in inventory)17
18# Iterate over key-value pairs19for fruit, count in sorted(inventory.items()):20    print(f"{fruit}: {count}")21
22# Classic hash map use case: counting frequencies23words = "the quick brown fox jumps over the lazy dog the end".split()24freq = {}25for word in words:26    freq[word] = freq.get(word, 0) + 127
28print("Occurrences of the:", freq["the"])29print("Most common word:  ", max(freq, key=freq.get))
Esegui questo codice nel playground Python

Domande frequenti sulla hash map

Qual è la differenza tra una hash map e una tabella hash?
Sono essenzialmente la stessa struttura: un array di bucket indirizzati dall'hash della chiave. Nell'uso comune "tabella hash" indica spesso un insieme di chiavi o la tecnica in generale, mentre "hash map" sottolinea la memorizzazione di coppie chiave-valore. Alcuni linguaggi fanno anche una distinzione sulla thread safety (ad es. Hashtable e HashMap in Java), ma l'algoritmo di base è identico.
Qual è la complessità temporale di una hash map?
Put, get ed eliminazione sono O(1) in media con una buona funzione di hash e un fattore di carico basso. Nel caso patologico in cui tutte le chiavi collidono in un unico bucket, degradano a O(n), ed è per questo che il ridimensionamento e un buon hashing contano.
Come gestisce una hash map due chiavi che finiscono nello stesso bucket?
Risolve la collisione. Questa visualizzazione usa il concatenamento separato: ogni bucket contiene una piccola lista e una nuova coppia la cui chiave finisce lì viene aggiunta a quella lista. Nella ricerca, la mappa scorre la breve catena alla ricerca della chiave corrispondente. La tecnica alternativa è l'indirizzamento aperto, che cerca un'altra posizione libera nell'array.
Hash map o albero binario di ricerca: quale usare?
Usa una hash map quando ti serve solo la ricerca per chiave esatta e vuoi operazioni O(1) in media. Usa un albero binario di ricerca bilanciato (come una TreeMap o una std::map) quando ti servono chiavi in ordine, query su intervalli o ricerche di predecessore/successore, che costano O(log n). Il BST sacrifica un po' di velocità in cambio di garanzie di ordine che una hash map non può offrire.
Cos'è il fattore di carico e perché fa scattare il ridimensionamento?
Il fattore di carico è il rapporto tra le voci memorizzate e il numero di bucket. Quando cresce, le catene si allungano e le ricerche medie rallentano, quindi la maggior parte delle implementazioni si ridimensiona (di solito raddoppiando i bucket e ricalcolando l'hash di tutto) quando supera una soglia come 0.75. Il ridimensionamento è O(n) ma raro, quindi il suo costo si ammortizza e le operazioni restano O(1) in media.
Posso usare un oggetto mutabile come una lista come chiave di una hash map?
Di solito no. Le chiavi devono essere hashable e il loro hash deve restare costante mentre sono nella mappa: Python, per esempio, solleva TypeError: unhashable type per una list. Se modifichi una chiave dopo averla inserita, il suo hash cambia e la mappa non riesce più a trovarla nel bucket giusto, perdendo la voce senza avvisarti. Usa chiavi immutabili come stringhe, numeri o tuple.
Illustrazione dei linguaggi di programmazione di Coddy

Padroneggia gli algoritmi con Coddy

INIZIA