Hashing.

Slides:



Advertisements
Presentazioni simili
Algoritmi e Strutture Dati
Advertisements

Tecnologia delle basi di dati: Strutture fisiche di accesso
Argomenti della lezione
Estendere i linguaggi: i tipi di dato astratti
Capitolo 8 Array Lucidi relativi al volume: Java – Guida alla programmazione James Cohoon, Jack Davidson Copyright © The McGraw-Hill Companies srl.
1 Astrazioni sui dati : Specifica ed Implementazione di Tipi di Dato Astratti in Java.
MultiSet, Liste Ordinate
LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.
Lez. 131 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Rappresentazione.
Realizzazione del file system
Hash Tables Indirizzamento diretto Tabelle Hash
Hash Tables Indirizzamento diretto Tabelle Hash Risoluzioni di collisioni Indirizzamento aperto.
Realizzazione del file system
Strutture dati elementari
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati.
STRUTTURE DATI e LABORATORIO II ESERCITAZIONE N°13 Heap massimo.
Esercizi su alberi binari
Tail recursion: esempio
Esercizi su alberi binari di ricerca
File.
Capitolo 7 Tavole hash Algoritmi e Strutture Dati.
Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale.
Capitolo 7 Tavole hash Algoritmi e Strutture Dati.
Introduzione alla Object Oriented Programming, OOP E.Mumolo. DEEI
E.Mumolo. DEEI Introduzione alla programmazione ad oggetti in C++ Object Oriented Programming, OOP E.Mumolo. DEEI
Allocazione dinamica della memoria
Astrazioni sul controllo Iteratori. 2 Nuove iterazioni Definendo un nuovo tipo come collezione di oggetti (p. es., set) si vorrebbe disporre anche di.
Algoritmi e Strutture Dati IV. Heap e Code di Priorità
Dizionari alberi bilanciati.
Argomenti della lezione
Hashing.
Gestione dei Progetti Software 2 (a.a. 2004/05) - Lezione 3 1 JAVA e Internet: il World Wide Web Internet: milioni di computer collegati fra di loro attraverso.
Lezione 4: Costrutti Condizionali Prof. Raffaele Montella.
Tabelle hash.
1 © Alberto Montresor Algoritmi e Strutture Dati Capitolo 7 - Tabelle hash Alberto Montresor Università di Trento This work is licensed under the Creative.
Algoritmi e Strutture Dati
Modello dati ALBERO Albero: Albero: insieme di punti chiamati NODI e linee chiamate EDGES EDGE: linea che unisce due nodi distinti Radice (root): in una.
Selezione (=scelta) con “if-else”
Tecniche HASH Corso (B) di Programmazione CDL in Informatica I livello A.A DIB - Università di Bari dal materiale didattico (aa ) di.
Algoritmi e Programmazione Avanzata
Metodo della moltiplicazione
1.Scrivere una funzione per cercare un numero x in una lista circolare di interi. La funzione deve restituire NULL se il numero non esiste. 2.Scrivere.
Corso di informatica Athena – Periti Informatici
Hashing.
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
Fopndamenti di programmazione. 2 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe.
Tail recursion: esempio
Esercizi.
Capitolo 7 Tavole hash Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
1 Record, tabelle, relazioni F. Bombi 1 novembre 2001.
Fondamenti di informatica Oggetti e Java Luca Cabibbo Luca Cabibbo – Fondamenti di informatica: Oggetti e Java Copyright © 2004 – The McGraw-Hill Companies.
Implementazione di dizionari Problema del dizionario dinamico Scegliere una struttura dati in cui memorizzare dei record con un campo key e alcuni altri.
Heap concetti ed applicazioni. maggio 2002ASD - Heap2 heap heap = catasta condizione di heap 1.albero binario perfettamente bilanciato 2.tutte le foglie.
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
AlgoLab - Pile e Code Pile e code Laboratorio di Algoritmi 02/03 Prof. Ugo de’ Liguoro.
Capitolo 6 Iterazione Lucidi relativi al volume: Java – Guida alla programmazione James Cohoon, Jack Davidson Copyright © The McGraw-Hill Companies.
Risoluzione delle collisioni con indirizzamento aperto Con la tecnica di indirizzamento aperto tutti gli elementi stanno nella tavola. La funzione hash.
Algoritmi e Strutture Dati Strutture Dati Elementari.
Archivi Esempi Movimenti contabili di un’azienda
Prog2 a.a. 2001/ Albero binario di ricerca Un albero binario di ricerca é un albero binario in cui ogni nodo ha un’etichetta.
Hashing. 2 argomenti Hashing Tabelle hash Funzioni hash e metodi per generarle Inserimento e risoluzione delle collisioni Eliminazione Funzioni hash per.
Algoritmi e Strutture Dati
1 Progettazione dettagliata di un Tipo di Dato Astratto: l’ambiente di metodi.
Public class SimpleHash { //DICHIARAZIONE DELLE VARIABILI DI ISTANZA //tabella hash private int[] table; //dimensione della tabella (meglio se numero primo)
1 Progettare un Tipo di Dato Astratto. 2 Scelte di Progetto (astrazione) 4 Caratteristiche degli oggetti –Modificabilità 4 Scelta delle operazioni –Realizzare.
Capitolo 7 Tavole hash Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
Esercizi.
30/10/01Array 1  Un array e’ una struttura dati che contiene piu’ valori del medesimo tipo.  La lunghezza di un array e’ stabilita quando l’array viene.
6/11/01Ordinamento 1 Un esempio di algoritmi: ordinamento.
Transcript della presentazione:

Hashing

argomenti Hashing Funzioni hash per file Tabelle hash Funzioni hash e metodi per generarle Inserimento e risoluzione delle collisioni Eliminazione Funzioni hash per file Hashing estendibile Hashing lineare Hashing

Richiamo sul concetto di dizionario Insieme di coppie del tipo <elemento, chiave> Le chiavi appartengono a un insieme totalmente ordinato Operazioni: insert(el, key) delete(key) search(key) Hashing

Tabelle hash Adatte per realizzare dizionari Generalizzazione del concetto di array Importanti nell’accesso a dati su memoria secondaria Gli accessi avvengono a memoria secondaria Costo degli accessi predominante Indirizzamento diretto: si associa ad ogni valore della chiave un indice di un array – ricerca in tempo O(1) Problemi? Hashing

Indirizzamento diretto Ogni chiave corrisponde a el. diverso dell’array Può portare a spreco di memoria Es.: 10000 studenti e matr.= No. decimale a 5 cifre 2 No. chiavi N-1 Hashing

Obiettivi N ~ No. Chiavi effettivamente usate Tempo di ricerca O(1) N ~ No. Chiavi effettivamente usate Tempo di ricerca O(1) D.: possibile? Nota: No. Chiavi possibili può essere >> N 2 No. chiavi N-1 Hashing

Tabella hash Dato l’insieme base di un dizionario: <T, h> T è una tabella h: K  {0,...,N-1} K insieme delle possibili chiavi {0,...,N-1} insieme delle posizioni nella tabella Hashing

Funzioni hash perfette e collisioni Funzione hash perfetta: k1!=k2  h(k1) != h(k2) Richiede N >= |K| Raramente ragionevole in pratica In generale N < |K| (spesso N << |K|) Conseguenza: k1!=k2 ma h(k1) == h(k2) è possibile  Collisione Es.: proporre una funzione hash perfetta nel caso in cui le chiavi siano stringhe di lunghezza 3 sull’alfabeto {a, b, c} Hashing

Requisiti di una funzione hash Uniformità semplice: Pr[h(k)=j] ~ 1/|K| La probabilità è calcolata rispetto alla distribuzione delle chiavi Intuitivamente, si desidera che gli elementi si distribuiscano nell’array in modo uniforme Difficile costruire funzioni che soddisfino la proprietà D.: perché? Hashing

Requisiti di una funzione hash/2 Esempio: sia |T|=5 e h(k)=k mod 5 {1, 7, 10, 14} {1, 6, 11, 16} 1 2 3 4 1 2 3 4 Non è nota la distribuzione delle chiavi Può aversi agglomerazione degli elementi In pratica: si cerca di avere indipendenza dai dati Hashing

Interpretazione delle chiavi Tra gli elementi di K è definito un ordinamento totale ma: Le chiavi non sono necessariamente numeri naturali (o persino numeri) Es.: stringhe Soluzione: associare a ciascuna chiave un intero Modalità dipendono da insieme delle chiavi e applicazione Hashing

Esempio: stringhe Possibile metodo: associare a ciascun carattere il valore ASCII e alla stringa il numero intero ottenuto in una base scelta Esempio: base 2, posizioni meno significative a destra Stringa = “p t”  chiave = 112*21+116*20=240 Ascii(‘p’)=112 Ascii(‘t’)=116 Hashing

Derivazione di funzioni hash Molti metodi Divisione Ripiegamento Mid-square Estrazione ........... Obiettivo: distribuzione possibilmente uniforme Differenze: Complessità Fenomeni di agglomerazione Hashing

Divisione h(k)=k mod |T| - Bassa complessità Attenzione ai fenomeni di agglomerazione No potenze di 2: se m=2p allora tutte le chiavi con i p bit meno significativi uguali collidono No potenze di 10 se le chiavi sono numeri decimali (motivo simile) In generale, la funzione dovrebbe dipendere da tutte le cifre della chiave (comunque rappresentata) Scelta buona in pratica: numero primo non troppo vicino a una potenza di 2 (esempio: h(k)=k mod 701 per |K|=2048 valori possibili) Hashing

Ripiegamento Chiave k suddivisa in parti k1,k2,....,kn h(k)=f(k1,k2,....,kn) Esempio: la chiave è un No. di carta di credito. Possibile funzione hash: 1. 4772 6453 7348  {477, 264, 537, 348} 2. f(477,264,537,348) = (477+264+537+348)mod 701 = 224 Hashing

Estrazione Si usa soltanto una parte della chiave per calcolare l’indirizzo Esempio: 6 cifre centrali del numero di carta di credito 4772 6453 7348  264537 Il numero ottenuto può essere ulteriormente manipolato L’indirizzo può dipendere da una porzione della chiave Hashing

Risoluzione delle collisioni I metodi si distinguono per la collocazione degli elementi che danno luogo alla collisione Concatenazione: alla i-esima posizione della tabella è associata la lista degli elementi tali che h(k)=i Indirizzamento aperto: tutti gli elementi sono contenuti nella tabella Hashing

Concatenazione h(k1)= h(k4)=0 h(k5)= h(k7)=h(k2)=4 1 2 3 4 1 2 3 4 k1 k4 k2 k5 k7 k2 Es.: h(k)=k mod 5 k1=0, k4=10 k5=9, k7=14, k2=4 Hashing

Concatenazione/2 insert(el, k): inserimento in testa alla lista associata alla posizione h(k) – costo O(1) search(k): ricerca lineare nella lista associata alla posizione h(k) – costo O(lungh. lista associata a h(k)) delete(k): ricerca nella lista associata a h(k), quindi cancellazione – costo O(lungh. lista associata a h(k)) Hashing

Indirizzamento aperto Tutti gli elementi sono memorizzati nella tabella Le collisioni vanno risolte all’interno della tabella Se la posizione calcolata è già occupata occorre cercarne una libera I diversi metodi ad indirizzamento diretto si distinguono per il metodo di scansione adottato La funzione hash dipende anche dal numero di tentativi effettuati Indirizzo=h(k, i) per l’i-esimo tentativo Hashing

Inserimento insert (el, k) { /* T denota la tabella */ i=0; while (h(k, i) <occupata> && (i<|T|)) i++; if (i < |T|) <inserisci el in pos. i> else <overflow> } Hashing

Ricerca search (k) { /* T denota la tabella */ i=0; while ((k!=key(T[h(k, i)])) && (i<|T|)) i++; if (i < |T|) <restituisci T[h(k, i)]> else <elemento assente> } Implementazione inefficiente Se elemento assente si esamina tutta la tabella Hashing

Cancellazione delete (k) { /* T denota la tabella */ search(k); if (<trovato>) <elimina elemento con chiave k> } Implementazione inefficiente Stessi motivi del caso precedente Hashing

Scansione La funzione h(k, i) deve essere tale che tutte le posizioni della tabella siano esaminate Sono possibili diverse forme per la funzione h(k,i) Scansione lineare Scansione quadratica Hashing doppio Si differenziano per complessità e comportamento rispetto a fenomeni di agglomerazione Hashing

Scansione lineare h(k, i) = (h’(k)+i) mod |T|, dove h’(k) è una funzione di hashing Si scandiscono tutte le posizioni nella sequenza T[h’(k)], T[h’(k)]+1, .... T[|T|], 0, 1, ...., T[h’(k)]-1 Possibilità di agglomerazione primaria: gli elementi si agglomerano per lunghi tratti Hashing

Agglomerazione primaria h(k, i) = (h’(k)+i) mod 101, h’(k)=k mod 101 1 2 {2, 103, 104, 105,....} Caso estremo, ma il problema esiste 100 Hashing

Scansione quadratica h(k, i) = (h’(k)+c1i+c2i2) mod |T|, dove h’(k) è una funzione di hashing, c1 e c2 sono costanti Es.: h(k, i) = h’(k)+i2, h(k, i+1) = h’(k)-i2, i=1,..., (|T|-1)/2 Possibilità di agglomerazione secondaria: se h’(k1)= h’(k2)  h’(k1,i)= h’(k2,i) Descrivere h(k, i) quando h’(k)=k mod |5| Hashing

Hashing doppio h(k, i) = (h1(k)+ih2(k)) mod |T|, dove h1(k) e h2(k) sono funzioni di hashing Es.: h(k, i) = h’(k)+i2, h(k, i+1) = h’(k)-i2, i=1,..., (|T|-1)/2 Anche la modalità di scansione dipende dalla chiave L’hashing doppio riduce i fenomeni di agglomerazione Hashing

Implementazione Java Tabella rappresentata con array Chiavi di tipo Comparable Convertite in String Funzione hash applicata a oggetti String i = 0: h(S, 0) = h(S) S una stringa i > 0: h(S, i) = h(S) + cost * i cost = 3 Hashing

Implementazione Java/cont. Due array per rappresentare la tabella: Comparable table[] - entry della tabella Boolean isActive[] - per la gestione isActive[i] = true se table[i] != null oppure table[i] == null, ma table[i] ha precedentemente contenuto un elemento Problema: efficienza I metodi di ricerca e cancellazione visti precedentemente possono essere poco efficienti Es.: se elemento assente viene scandita l’intera tabella Hashing

Esempio: ricerca Scansione lineare Ricerca chiave 27 33 Scansione lineare h(k, i) = k mod 11 + 3*i Ricerca chiave 27 Posizione (5) occupata da elemento di chiave 16 Come facciamo a sapere che possiamo interrompere la ricerca? Necessario riconoscere le posizioni che sono state occupate da elementi poi rimossi - 2 - 15 16 - - 27 - - Hashing

Classe HashTable public class HashTable implements Dictionary_adt { private static final int DEFAULT_TABLE_SIZE = 23; /** The array of elements. */ protected Comparable [ ] table; // The array of elements protected boolean [] isActive; protected int currentSize; // The number of occupied cells protected boolean isRehashable; //true if table can be expanded protected int k =3; //Coefficient for LinearProbing /* Seguono costruttori */ Hashing

Classe HashTable/2 /* Costruttore principale */ public HashTable(int size, boolean rehash) { /* Alloca due array table[] e isActive[] di simensione size. Se rehash == true -> la tabella puo’ essere espansa se e’ piena per piu’ della meta’. Inizializza la tabella: table[i] = null e isActive[i] = false per ogni i */ } /* Altri costruttori */ /* Seguono i metodi */ Hashing

Classe HashTable/3 /* La nostra funzione hash */ public static int hash(String key, int tableSize) { int hashVal = 0; for( int i = 0; i < key.length( ); i++ ) hashVal = 37 * hashVal + key.charAt( i ); hashVal %= tableSize; /* | hashVal | < tableSize */ if( hashVal < 0 ) /* si puo’ avere overflow -> hashVal < 0 */ hashVal += tableSize; /* Cosi’ hashVal diventa > 0 */ return hashVal; } /* Altri metodi */ Hashing

Classe HashTable/4 /* Inserimento */ public Object insert(Comparable key ) { int collisionNum = 0; /* No. collisioni */ int initialPos = hash( key.toString(),table.length ); int currentPos=initialPos; int insertPos= -1; /* Se alla fine vale -1 -> tabella piena (caso di tabella non espandibile) */ /* Continua … */ Hashing

Classe HashTable/5 while(collisionNum<table.length-1) { if (table[currentPos] == null) { /* trovata posizione libera */ if (insertPos == -1) insertPos = currentPos; if (!isActive[currentPos]) break; /* se posizione non attiva -> elemento non presente, puoi uscire dal ciclo while */ } /* End if */ else if (table[ currentPos ].compareTo( key )==0) { //table[currentPos]!= null System.out.println("Element "+ key +" is alredy in the hash table."); return key; } /* End else */ currentPos = initialPos + k * ++collisionNum; currentPos = currentPos % table.length; // Implement the mod } /* End while */ Hashing

Classe HashTable/6 if (insertPos!= -1) { /* E’ stata trovata una posizione libera */ table[ insertPos ] = key; isActive[ insertPos] = true; ++currentSize; System.out.println("Insertion of "+key+": in position " +currentPos); if((isRehashable)&&(currentSize > table.length/2)) { System.out.println("Rehash!"); rehash(); } /* End if */ return key; } /* End if */ else { /* Non e’ stata trovata una posizione libera */ System.out.println("Insertion impossible: hash table full"); return null; } /* End else */ } /* End inserimento */ Hashing

Classe HashTable/7 public Comparable remove(Comparable key ){ int collisionNum = 0; int initialPos = hash( key.toString(),table.length ); int currentPos=initialPos; /* Variabili hanno stesso significato che in insert() */ /* Continua */ Hashing

Classe HashTable/8 while ( ( ((table[currentPos] == null)&& isActive[currentPos] )|| ( (table[currentPos] != null) && (table[currentPos].compareTo(key)!=0))) && (collisionNum < table.length-1)) { currentPos = initialPos + k * ++collisionNum; // Compute ith probe currentPos = currentPos % table.length; // Implement the mod } /* End while */ /* Esce da ciclo while se elemento trovato o tutta la tabella esaminata senza trovare elemento con chiave cercata */ /* Continua */ Hashing

Classe HashTable/9 /* Continua dalla slide precedente */ if ((table[currentPos]==null)||table[currentPos].compareTo(key) !=0) { System.out.println("Element "+ key +" isn't in the hash table."); return null; } /* End if */ else{ System.out.println("Element "+ key +" is in the hash table."); table[currentPos]=null; return key; } /* End else */ } /* End remove() */ /* Altri metodi e fine della classe HashTable */ Hashing

Classe HashTable/cont. Metodo find() implementa la ricerca Approccio identico ai casi precedenti Ricerca, inserimento e cancellazione piu’ efficienti Vengono controllati soltanto gli elementi non nulli o con corrispondente campo isActive a true Gli elementi con campo isActive a true sono quelli che hanno contenuto un elemento in seguito rimosso Hashing

Hashing estendibile E’ usato nella gestione di file, la cui dimensione può variare. Es.: file ad accesso diretto Il file è organizzato in bucket, ciascuno dei quali ha una dimensione fissa Gli indirizzi sono associati ai bucket La funzione hash restituisce in questo caso un puntatore al bucket Hashing

Hashing estendibile/2 File h(k) restituisce una stringa binaria b I bit più significativi di b sono usati per determinare l’indirizzo del bucket 2 Lungh. locale Bucket 00 Lungh. globale h(k)=11001 2 2 Bucket 01 00 01 10 1 Bucket 1 11 Indice Hashing

Esempio File File Dim. Bucket = 4 01100 00001 h(k)=00101 00101 00001 2 Bucket 0 Bucket 00 01100 00001 00001 00101 h(k)=00101 1 2 2 00 Bucket 01 1 01 01100 1 10 Indice Bucket 1 10010 11 Indice 1 10010 Bucket 1 Dim. Bucket = 4 Hashing

H. estendibile - Inserimento extHashInsert (el, k) { /* L=lunghezza globale */ str=h(k); /* LS= lunghezza str */ p=indice[pattern[LS-1...LS-L]]; if (<Bucket puntato da p non pieno) <inserisci el> else { <suddividi bucket> /* l=lunghezza locale bucket*/ l++; } if (l > L) <Raddoppia indice> L++; Hashing