ADT Dizionario Come nella Mappa: ● un Dizionario è un contenitore di elementi del tipo (k,v) dove k è la chiave e v è il suo corrispondente valore. ● ogni elemento (k,v) viene detto entrata (entry) del Dizionario. ● chiavi e valori possono essere oggetti di qualsiasi tipo. Diversamente dalla Mappa: ● sono permesse entrate multiple con la stessa chiave. Strutture Dati ADT Dizionario Esistono due tipi di dizionari: ● ● dizionari non ordinati (non è definita alcuna relazione d'ordine totale sulle chiavi: l'unico test permesso fra chiavi è quello di uguaglianza) dizionari ordinati (è definita una relazione d'ordine totale sulle chiavi) Strutture Dati ADT Dizionario Metodi fondamentali – size(): restituisce il numero di entrate in D. – isEmpty(): verifica se D è vuoto. – find(k): se D contiene una entrata con chiave k, restituisce tale entrata, altrimenti restituisce null. – findAll(k): restituisce una collezione iterabile contenente tutte le entrate con chiave k. – insert(k,v): inserisce una entrata con chiave k e valore v in D; restituisce l'entrata creata. – remove(e): rimuove da D una entrata e, restituendo l'entrata rimossa; si ha un errore se e non è in D. – entries(): restituisce una collezione iterabile delle entrate in D. Strutture Dati ADT Dizionario Interfaccia public interface Dictionary<K,V> { public int size(); public boolean isEmpty(); public Entry<K,V> find(K key) throws InvalidKeyException; public Iterable<Entry<K,V>> findAll(K key) throws InvalidKeyException; public Entry<K,V> insert(K key, V value) throws InvalidKeyException; public Entry<K,V> remove(Entry<K,V> e) throws InvalidEntryException; public Iterable<Entry<K,V>> entries(); } Strutture Dati ADT Dizionario Implementazione con liste non ordinate lista S Le entrate del dizionario D vengono mantenute in una lista non ordinata S non è definita alcuna relazione d'ordine totale sulle chiavi Strutture Dati ADT Dizionario Implementazione con liste non ordinate Algorithm findAll(k): Crea una lista S inizialmente vuota for each entry e in D.entries() do if e.getkey() = k then S.addLast(e) return S Algorithm insert(k,v): Crea una nuova entrata e = (k,v) S.addLast(e) {lecito perché S non è ordinata} return e Strutture Dati ADT Dizionario Implementazione con liste non ordinate Algorithm remove(e): {assumiamo che e non memorizzi la sua position in S} for each position p in S.positions() do if p.element() = e then S.remove(p) return e lancia una InvalidEntryException {non esiste l'entrata e in D} Algorithm entries(): return S Strutture Dati ADT Dizionario Implementazione con liste non ordinate Analisi: spazio: O(n) tempo: ● ● insert: O(1) find e remove: O(n) (nel caso pessimo si deve scorrere tutta la lista) la performance di remove può essere portata ad O(1) se ogni entrata di D memorizza la sua posizione nella lista S Questa implementazione è opportuna solo per dizionari di piccola taglia o dizionari in cui gli inserimenti sono le operazioni più comuni, mentre le ricerche e le rimozioni sono eseguite di rado (per esempio record di login a una workstation) Strutture Dati ADT Dizionario Implementazione con tabelle hash Possiamo usare una tabella hash con separate chaining per risolvere le collisioni Bucket array A Dizionario basato su lista 0 1 2 3 4 … Ogni cella A[i] mantiene un dizionario che contiene tutte le entrate con chiave k tale che h(k) = i Strutture Dati ADT Dizionario Implementazione con tabelle hash A: bucket array N: dimensione del bucket array n: numero di entrate del dizionario λ: massimo load factor della tabella hash h: funzione hash Algorithm insert(k,v): if (n + 1) / N > λ then raddoppia la taglia del bucket array e fai il rehash delle chiavi e := A[h(k)].insert (k,v) n:= n + 1 A[h(k)] è un dizionario return e quindi possiamo usare il metodo insert per inserire una nuova entrata Strutture Dati ADT Dizionario Implementazione con tabelle hash Algorithm findAll(k): return A[h(k)].findAll (k) Algorithm remove(e): t := A[h(k)].remove (e) n=n–1 return t Strutture Dati ADT Dizionario Implementazione con tabelle hash Analisi: spazio: O(n) tempo: ● ● ● ● insert: O(1) remove: ● atteso: O(1) ● caso peggiore: O(n) find: ● atteso: O(1) ● caso peggiore: O(n) findAll: ● atteso: O(1 + s) dove s è il numero di chiavi restituite. ● caso peggiore: O(n) Strutture Dati