Hashing / Hash tabeller -- Kapitel 20 Hash? Varför en annan datastruktur? Konstant tid för både insert- och findoperationer Hash? Insert Find ”Daniel” =18 Hashfunktioner! Hash functioner använder associerade “key” ( som kan vara data i sig ) för att få fram datan. Hash funktionerna är olika för olika sorts data. Integers Images Strings Etc… Hashing integers? Tänk 16bit int => 0 – 65 535 Skapa int[] vec = new int[65536]; Add i => vec[i]++; Sök value j => Is vec[j] > 0? Ta bort value k => vec[k]--; Men för en ... Java int : 32bit 4 billion items => impractical! Exempel av hash funktion ”Daniel” D a n i e l 68 + 97 + 110 +105+ 101 +108 = 589 Men... Hur unik är den? hashfunc(”Daniel”) → 589 hashfunc(”leinaD”) → 589 Bättre lösning men….! hashfunc(”TestValue”) → 129310392 Wrapp värdet till ett visst intervall Vilken? Arraystorleken… En bättre hash funktion Ett bättre sätt att beräkna hash värdet Om vi har en text sträng av längd n+1 och alla tecken har index An, An-1,...,A0 gör s = AnXn + An-1Xn-1 +...+ A0X0 = = ((An)X + An-1)X +...+ A0 Använd hashValue = s % array.length Och då...... For example: ”Danne” (((’D’)128 + ’a’)128 + ’n’)128 + ’n’)128 + ’e’ = (((68)128 + 97)128 + 110)128 + 110)128 + 101 = 18 458 851 173 hashValue = 18 458 851 173 % array.length om length = 7919 (prim nummer) => hashValue = 18 458 851 173 % 7919 = 2690 Hur löser man kollision? Oavsätt hur unika keys en hashfunktionen tar fram, kollision alltid inträffas. Terminology Load factor # used positions LF # total avaliable positions Lösningar Linear probing ( undersökning ??) Quadratic probing Double hashing Separate chaining Linear probing Sök fram till näst lediga platsen. hashfunc( ) 10 18 X=18 X+1, X+2, X+3, X+4, X+5, ... Linear probing Fenomen kallat: Primary clusters Linear probing Bygger upp kluster Påverkar exekveringstiden för insert () och find()! Quadratic probing Försök undvika“primary clusters “ Snabare en linjär Kvadratisk inkrementation av undersökning avståndet X=18 X+12, X+22, X+32, X+42, X+52, ... Quadratic probing 32 = 9 1 2 1 4 Garantera att hitta fria platser om de finns Double hashing Använder en till hash funktion för att hitta fri plats. X = hash(obj); X2 = hash2(obj); X=18, X2=7 X+1*X2, X+2*X2, X+3*X2, X+4*X2, ... X=18, X2=7 18+1*7, 18+2*7, 17+3*7, 18+4*7, ... Double hash probing Hash2() = 3 3*3 1*3== 6 2*3= 39 Andra hash-funktionene Får inte returnera 0! Separate chaining Varje hash position har en länkad lista. Påverkar inte andra värde, probing görs bara i listan. Varje element I tabellen är en länkad lista. Separate chaining Insert H H H H H H H H H Jämförelse Linear probing Quadratic probing Kräver Load factor < 0.5 annars rehashing ?? Kräver prim tal för array storleken Separate chaining Enkel Kan resultera i linjär söktid LF < 1 Ingen dubblering, länkade listor är dinamiska ! Kan leda till linjär sökning men I verklighetet ganska kort Double hash probing Eliminerar kluster Implementation Quadratic prob. ... Object[] list = new Object[size]; // Prime length ... int hash(Object o) { int start= Math.abs(o.hashCode() % list.length); int quadNbr = 0; int index = start; while(list[index] != null) { index = start + Math.pow(++quadNbr, 2); } return pos; }