Mappe e dizionari
In questa pagina 5
Una mappa/dizionario è una collezione di entry (chiave, valore) che supporta ricerca, inserimento e rimozione per chiave. In Python è il tipo dict (Dizionari e insiemi in PythonADT mappa e insieme; dict con chiavi hashable, accesso, get, iterazione, conteggi e raggruppamenti; set e operazioni insiemistiche; tabelle hash e costo O(1) medio; Counter e defaultdict.Dizionari e insiemi in Python →); qui si studia come è fatto dentro. La corrispondenza con l'ADT di questa nota (Tipi di dato astrattiUn ADT è definito dalle operazioni e dal loro comportamento, non dalla rappresentazione; interfaccia e implementazione; realizzazione in Python con le classi e in C con header e tipo opaco; esempio di un ADT Frazione.Tipi di dato astratti →) è: d[k] = v put(k, v), d.get(k) get(k), del d[k] remove(k), d.keys(), d.values(), d.items() keySet(), values(), entrySet(). L'ADT ha varianti secondo due scelte: chiavi distinte o no, universo delle chiavi totalmente ordinato o no.
| Chiavi distinte | Universo ordinato | |
|---|---|---|
| Mappa | sì | no |
| Mappa ordinata | sì | sì |
| Multimappa o dizionario | no | no |
| Multimappa o dizionario ordinato | no | sì |
Nel testo adottato dizionario multimap. Le strutture studiate sono: tabelle hash per mappe non necessariamente ordinate (vedi Tabelle hashTabella hash per implementare una mappa: funzione hash = hash code + compression function, bucket array, separate chaining; hash code per numeri e stringhe (polynomial, cyclic shift), division e MAD; load factor, complessità al caso pessimo Theta(n) e medio O(1+lambda), rehashing; esempio svolto con inserimenti e collisioni.Tabelle hash →); alberi binari di ricerca, multi-way search tree e alberi (2,4) per mappe e dizionari ordinati (vedi Alberi binari di ricercaAlbero binario di ricerca come albero binario proprio con entry nei nodi interni e foglie vuote; inorder crescente; TreeSearch; get, put e remove (due casi, con predecessore inorder) in Theta(h); altezza fino a n-1; esempi di inserimenti; alberi aumentati con campi size e max e algoritmi di conteggio e interrogazione in O(h).Alberi binari di ricerca →, Multi-way search tree e alberi (2,4)Multi-way search tree (nodi con più entry, d figli e d-1 chiavi ordinate), ricerca in O(d_max h), un MWS tree con n entry ha n+1 foglie; albero (2,4): nodi con 2-4 figli e tutte le foglie alla stessa profondità, altezza Theta(log n) con dimostrazione, operazioni in Theta(log n); idea di overflow e underflow; tabella di confronto con gli alberi binari di ricerca.Multi-way search tree e alberi (2,4) →).
Applicazioni
- Database (anagrafica degli studenti): chiave = matricola, valore = informazioni dello studente.
- Compilatori, controllo dei tipi: chiave = nome della variabile, valore = tipo.
- Motori di ricerca: chiave = parola, valore = lista dei documenti che la contengono (lista invertita).
- Conteggio di frequenze: chiave = oggetto, valore = conteggio (ad esempio nell'analisi di sequenze biologiche, con oggetto = -mer, sequenza di caratteri).
L'ADT mappa
Definizione (ADT mappa). Mappa: entry con chiavi distinte provenienti da un dominio su cui è definito
=; concetto analogo a un indice (associative array: la chiave è l'indice di accesso).
Metodo Effetto get(k)se esiste restituisce , altrimenti nullput(k, v)se esiste lo sostituisce con e restituisce ; altrimenti inserisce e restituisce nullremove(k)se esiste lo toglie e restituisce , altrimenti nullkeySet(),values(),entrySet()iteratori sulle chiavi, sui valori, sulle entry
Esempio. Su una mappa vuota: put("a", 1) restituisce null, poi put("a", 2) restituisce 1, get("a") restituisce 2 e remove("a") restituisce 2.
Con get(k) che restituisce null per "assente", un valore null non è distinguibile da una chiave mancante: per questo di solito si vietano valori null.
Implementazioni semplici ma poco efficienti
- Lista (doppiamente) concatenata non ordinata:
get,put,removerichiedono la ricerca lineare della chiave, al caso pessimo (la mappa non ha ordine, quindi non si può fare di meglio: è la ricerca lineare di Ricerca lineare e binariaRicerca lineare su sequenze qualsiasi in O(n); ricerca binaria su sequenze ordinate in O(log n), versione iterativa e ricorsiva, invariante e errori di indice; modulo bisect.Ricerca lineare e binaria →; sapendo l'ordine delle chiavi si potrebbe usare la ricerca binaria, ma non su una lista concatenata, dove l'accesso al nodo costa , vedi Liste, pile e codeRipasso degli ADT elementari: lista index-based (array) e position-based (lista doppiamente concatenata con sentinelle), pila LIFO, coda FIFO, deque, iteratori; interfacce, implementazioni e costi; array estendibile e coda circolare.Liste, pile e code →). - Array di taglia : se le chiavi sono interi nell'intervallo si usa la chiave come indice e le tre operazioni costano . Ma lo spazio è , spesso sproporzionato: il codice fiscale ha caratteri (nove lettere e sette cifre, quindi circa chiavi possibili) contro qualche milione di cittadini ( celle di memoria sono molto più di qualunque memoria disponibile, vedi Memoria principale a semiconduttoreCella di memoria e operazioni; RAM dinamica (condensatore, refresh) e statica (flip-flop), confronto; ROM, PROM, EPROM, EEPROM e flash; organizzazione dei chip e dei moduli con calcolo di linee di indirizzo e numero di chip; DRAM sincrona e DDR; errori e codici di correzione.Memoria principale a semiconduttore →); inoltre servirebbe una corrispondenza chiave intero calcolabile in tempo costante. Il calcolo: ciascuna delle posizioni di lettera ha valori e ciascuna delle posizioni di cifra ne ha , quindi le combinazioni sono (principio moltiplicativo del calcolo combinatorioNegli spazi uniformi bisogna contare: principio di moltiplicazione, disposizioni con ripetizione n^k, disposizioni semplici n!/(n−k)!, permutazioni n!, combinazioni (n su k); estrazioni con e senza reinserimento e distribuzione ipergeometrica.Calcolo combinatorio per la probabilità →).
La tabella hash nasce per tenere il tempo costante senza lo spazio proporzionale a .
Dizionario (multimap)
Definizione (dizionario o multimap). Ammette più entry con la stessa chiave. Metodi caratteristici:
get(k): restituisce una collezione (anche vuota) con tutti i valori associati a ;put(k, x): inserisce sempre una nuova entry , senza toccare le altre con la stessa chiave; non restituisce nulla;remove(k, v): toglie una entry con chiave e valore , se esiste; non restituisce nulla.
Esempio. Dopo put(k, 1) e put(k, 2), get(k) restituisce la collezione ; remove(k, 1) lascia .
Traccia dell'implementazione con una mappa di liste, partendo da una mappa vuota:
| operazione | contenuto della mappa dopo | note |
|---|---|---|
put("x", 1) |
la entry non c'era: la si crea con la lista | |
put("x", 2) |
la entry c'era: si aggiunge alla lista | |
put("y", 7) |
altra chiave, altra entry | |
remove("x", 1) |
si cerca in ( confronti al più) | |
remove("y", 7) |
è vuota: si toglie la entry dalla mappa |
Implementazione con una mappa: le entry sono con collezione non vuota dei valori di (una doppia lista); rappresenta in modo compatto le entry . get e put costano come nella mappa (si aggiunge a se la entry esiste, altrimenti si crea con il solo ); remove(k, v) costa come nella mappa più un termine per cercare in ; se resta vuota si toglie la entry dalla mappa. In alternativa si modificano alberi di ricerca e alberi (2,4) per ammettere chiavi uguali.
Errori comuni
- Confondere mappa (chiavi distinte,
putsostituisce) e dizionario (putaggiunge sempre). - Usare una struttura che richiede l'ordine (albero di ricerca) per chiavi senza ordine totale.
- Dimenticare che
putrestituisce il vecchio valore.
Versione ripasso
- Collezione di entry (chiave, valore) con ricerca, inserimento e rimozione per chiave. Varianti: mappa (chiavi distinte), mappa ordinata (universo totalmente ordinato), dizionario o multimap (chiavi ripetute), dizionario ordinato (in Python: Dizionari e insiemi in PythonADT mappa e insieme; dict con chiavi hashable, accesso, get, iterazione, conteggi e raggruppamenti; set e operazioni insiemistiche; tabelle hash e costo O(1) medio; Counter e defaultdict.Dizionari e insiemi in Python →).
- Mappa:
get(k)restituisce il valore onull;put(k,v)sostituisce e restituisce il vecchio valore, oppure inserisce e restituiscenull;remove(k)toglie e restituisce il valore;keySet(),values(),entrySet(). Esempio:put("a",1)dànull,put("a",2)dà1,remove("a")dà2. - Strutture: tabelle hash per le mappe non ordinate (vedi Tabelle hashTabella hash per implementare una mappa: funzione hash = hash code + compression function, bucket array, separate chaining; hash code per numeri e stringhe (polynomial, cyclic shift), division e MAD; load factor, complessità al caso pessimo Theta(n) e medio O(1+lambda), rehashing; esempio svolto con inserimenti e collisioni.Tabelle hash →); alberi binari di ricerca, multi-way search tree e (2,4) per le mappe ordinate (vedi Alberi binari di ricercaAlbero binario di ricerca come albero binario proprio con entry nei nodi interni e foglie vuote; inorder crescente; TreeSearch; get, put e remove (due casi, con predecessore inorder) in Theta(h); altezza fino a n-1; esempi di inserimenti; alberi aumentati con campi size e max e algoritmi di conteggio e interrogazione in O(h).Alberi binari di ricerca →, Multi-way search tree e alberi (2,4)Multi-way search tree (nodi con più entry, d figli e d-1 chiavi ordinate), ricerca in O(d_max h), un MWS tree con n entry ha n+1 foglie; albero (2,4): nodi con 2-4 figli e tutte le foglie alla stessa profondità, altezza Theta(log n) con dimostrazione, operazioni in Theta(log n); idea di overflow e underflow; tabella di confronto con gli alberi binari di ricerca.Multi-way search tree e alberi (2,4) →).
- Applicazioni: anagrafica (chiave = matricola), tipo delle variabili nei compilatori, lista invertita nei motori di ricerca, conteggio di frequenze.
- Lista non ordinata:
get,put,removein con ricerca lineare (vedi Ricerca lineare e binariaRicerca lineare su sequenze qualsiasi in O(n); ricerca binaria su sequenze ordinate in O(log n), versione iterativa e ricorsiva, invariante e errori di indice; modulo bisect.Ricerca lineare e binaria →). - Array indicizzato dalla chiave: , ma spazio . Il codice fiscale ha circa combinazioni, troppe per qualunque memoria.
- Dizionario (multimap):
get(k)restituisce una collezione anche vuota,put(k,x)aggiunge sempre,remove(k,v)toglie una coppia. Realizzato con una mappa di coppie : stessi costi, più per cercare inremove. Traccia:put("x",1),put("x",2),put("y",7),remove("x",1),remove("y",7)lascia la sola entry("x",[2]). - Errori tipici: scambiare mappa e dizionario; usare un albero di ricerca su chiavi senza ordine totale; dimenticare che
putrestituisce il vecchio valore.