Sid 1 Kapitel 7: Sökning (Hashning) Hashning

Relevanta dokument
Tommy Färnqvist, IDA, Linköpings universitet. 1 ADT Map/Dictionary Definitioner Implementation... 2

Magnus Nielsen, IDA, Linköpings universitet

Datastrukturer och algoritmer. Innehåll. Tabell. Tabell - exempel. Gränsyta till Tabell. Tabell. Modell. Hashtabell Relation, lexikon.

Avbildningar och hashtabeller. Koffman & Wolfgang kapitel 7, mestadels avsnitt 2 4

Datastrukturer. föreläsning 6. Maps 1

Tommy Färnqvist, IDA, Linköpings universitet. 1 ADT Map/Dictionary Definitioner Implementation... 2

Innehåll. F7: Tabell, hashtabell, relation & lexikon. Gränsyta till Tabell. Tabell. Tabell Hashtabell Relation Lexikon.

Sökning. Översikt. Binärt sökträd. Linjär sökning. Binär sökning. Sorterad array. Linjär sökning. Binär sökning Hashtabeller

Grundläggande datalogi - Övning 4

Föreläsning 6 Datastrukturer (DAT037)

Innehåll. Föreläsning 10. Specifikation. Mängd. Specifikation. Konstruktion av mängd. Mängd Lexikon Hashtabell

TENTAMEN I DATASTRUKTURER OCH ALGORITMER DVG B kl. 14:00-19:00

Hashtabeller. TDA416, lp3 2016

Föreläsning 8. Mängd, Avbildning, Hashtabell

Algoritmer och datastrukturer

Programkonstruktion och. Datastrukturer

Interfacen Set och Map, hashtabeller

Diskutera. Hashfunktion

Föreläsning 10 Innehåll

Programmering för språkteknologer II, HT2011. Rum

Symboliska konstanter const

Föreläsning 8. Mängd, Avbildning, Hashtabell

Hashing Bakom kulisserna på Pythons dictionary

Hashing Bakom kulisserna på Pythons dictionary. Leta i listor Osorterade listor. Leta i listor Sorterade listor

Föreläsning 10 Innehåll. Diskutera. Hashtabeller. Hashfunktion. hashfunktion. hashkod (ett heltal)

Föreläsning 5 Datastrukturer (DAT037)

Inlämningsuppgift och handledning

Föreläsning 11 Innehåll

Hashing Bakom kulisserna på Pythons dictionary

Tentamen Datastrukturer D DAT 035/INN960

Datastrukturer och algoritmer

Inlämningsuppgift och handledning. Föreläsning 11 Innehåll. Diskutera. Hashtabeller

Tommy Färnqvist, IDA, Linköpings universitet. 1 Administrativ information Upplägg... 1

Prov i DAT 312: Algoritmer och datastrukturer för systemvetare

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

Lösningsförslag för tentamen i Datastrukturer (DAT037) från

Tommy Färnqvist, IDA, Linköpings universitet

DAI2 (TIDAL) + I2 (TKIEK)

Innehåll. Föreläsning 12. Binärt sökträd. Binära sökträd. Flervägs sökträd. Balanserade binära sökträd. Sökträd Sökning. Sökning och Sökträd

Innehåll. Sökning och hashtabeller. En bilsamling att söka i. En bil-klass att söka efter. Hur hittar vi alla bilar som uppfyller ett annat villkor

Algoritmer och datastrukturer 2012, fo rela sning 8

Föreläsning 10 Datastrukturer (DAT037)

Tentamen Datastrukturer D DAT 035/INN960

Tentamen Datastrukturer D DAT 035/INN960 (med mycket kortfattade lösningsförslag)

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

Föreläsning 6: Introduktion av listor

Datastrukturer. föreläsning 10. Maps 1

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

Tentamen kl Uppgift 4. Uppgift 5

Föreläsning 9 Datastrukturer (DAT037)

Föreläsning Datastrukturer (DAT037)

Föreläsning Datastrukturer (DAT036)

Övning från förra gången: readword

Tentamen Datastrukturer D DAT 036/DIT960

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Programmering för Språkteknologer II. Innehåll. Associativa datastrukturer. Associativa datastrukturer. Binär sökning.

Tentamen Programmeringsteknik II och NV2 (alla varianter) Skriv bara på framsidan av varje papper.

Övningsuppgifter #11, Programkonstruktion och datastrukturer

OMTENTAMEN I DATASTRUKTURER OCH ALGORITMER DVG B kl. 08:15-13:15

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor

Lösningsförslag för tentamen i Datastrukturer (DAT036) från

Tentamen Programmeringsteknik II för STS Skrivtid: Inga hjälpmedel.

Programkonstruktion och. Datastrukturer

Tentamen Datastrukturer för D2 DAT 035

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Länkade listor kan ingå som en del av språket, dock ej i C Länkade listor är ett alternativ till:

Träd Hierarkiska strukturer

Tentamen Programmeringsteknik 2 och MN Skrivtid: Inga hjälpmedel.

13 Prioritetsköer, heapar

Det är principer och idéer som är viktiga. Skriv så att du övertygar rättaren om att du har förstått dessa även om detaljer kan vara felaktiga.

Lösningar Datastrukturer TDA

F5: Debriefing OU2, repetition av listor, träd och hashtabeller. Carl Nettelblad

Exempeltenta GruDat 2002/2003

Sökning och sortering

Tentamen i Algoritmer & Datastrukturer i Java

Datastrukturer och algoritmer

Hashtabeller! (& kanske lite sortering)

Datastrukturer. föreläsning 3. Stacks 1

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Programmering för språkteknologer II, HT2014. Rum

Enkla datatyper minne

Namn: (Ifylles av student) Personnummer: (Ifylles av student) Tentamensdatum: Tid: Hjälpmedel: Inga hjälpmedel

TDIU01 - Programmering i C++, grundkurs

SP:PROG3 HT12 Tenta

Självbalanserande AVL-träd Weiss, avsnitt 4.4

Karlstads Universitet, Datavetenskap 1

Databaser Design och programmering Minnesteknik Minnesteknik, forts Utvecklingen Hårddisk Hårddisk, forts

Föreläsning Datastrukturer (DAT037)

Det är principer och idéer som är viktiga. Skriv så att du övertygar rättaren om att du har förstått dessa även om detaljer kan vara felaktiga.

Datastrukturer och algoritmer

Ekvivalensrelationer

Datastrukturer och algoritmer. Föreläsning 15 Inför tentamen

Databaser - Design och programmering. Minnesteknik. Minnesteknik, forts. Hårddisk. Primärminne (kretsteknik) Fysisk design av databasen

Tentamen med lösningsförslag Datastrukturer för D2 DAT 035

Lösningsförslag till tentamen Datastrukturer, DAT037,

Tentamen (del 2) (4 högskolepoäng) i Programkonstruktion och datastrukturer (1DL201)

Föreläsning 4 Datastrukturer (DAT037)

Öppna filer och filsystem i PintOS Hemuppgift TDDI81, 21/

Datastrukturer. föreläsning 10. Maps 1

Transkript:

Sid 1 Hashning 7-1 Hashning är en teknik för att göra insättningar, borttag och sökningar i en tabell, på en konstant tid. Hashning stödjer ej operationer av ordnande karaktär som t ex:» finn minsta/största.» skriv ut posterna i nyckel-ordning. I detta avsnitt skall vi diskutera Några metoder för att implementera Hash-tabeller. Jämföra dessa metoder. Påvisa applikationer vid vilka hashning används. Jämföra Hash-tabeller med binära sökträd. Grundläggande idé 7-2 Den ideala hash-tabellen är som datastruktur bara ett fält av fix storlek innehållande nycklarna. Tabellstorleken är Hsize. Konventionen är att låta tabellen gå från 0 till Hsize-1. Typiskt är nyckeln en sträng med ett associerat värde. Varje nyckel mappas till ett tal i intervallet [0,Hsize-1] och posten placeras i motsvarande cell. Denna mappning kallas för en hash-funktion. Frågeställningar: Hur väljer vi funktion? Hur hanteras situationen när två nycklar hashar till samma värde (kollision)? Hur bestäms tabellstorleken?

Sid 2 Hashfunktionen 7-3 A B Hashfunktionen krymper datatypen A till datatypen B. Hash-funktionen. 7-4 Huvudkrav på hash-funktionen snabb att beräkna. ge en god spridning, d v s en jämn fördelning av indexvärden. hash(key)= key mod Hsize. (Divisionsmetoden) är normalt en godtagbar lösning om» nycklarna är heltal.» om inte key har någon speciell oönskad egenskap. Oftast önskvärt att tabellstorleken är ett primtal. ger funktion enkel att beräkna samt en jämn spridning. Vanligen är nycklarna strängar och hash-funktionen måste väljas med större omsorg.

Sid 3 Exempel 1. Nycklarna är strängar. 7-5 En möjlighet är att helt enkelt addera ihop de olika tecknens ASCII-värden. Funktionen blir : unsigned int hash( const char * Key, const int hsize) const char * Keyptr = Key; unsigned int hashval=0; while (*Keyptr ) hashval += *Keyptr++; return hashval % hsize; Den hash-funktionen är enkel att beräkna, men om tabellstorleken är stor distribuerar den dock inte nycklarna på ett bra sätt. Exempel 2. Nycklarna är strängar. 7-6 unsigned int hash( const char * Key, const int hsize) return (Key[0]+27*Key[1]+729*Key[2]) % hsize; Antar att key åtminstone har längden två. 27 representerar antal bokstäver i alfabetet plus blanktecknet och 729 är 27 2. Fungerar ändå inte bra eftersom det engelska språket inte ger en slumpmässigt likformig fördelning.

Sid 4 Exempel 3. Nycklarna är strängar. 7-7 unsigned int hash( const char * Key, const int hsize) const char * Keyptr = Key; unsigned int hashval=0; while (* Keyptr ) hashval = (hashval << 5) + *Keyptr++; return hashval % hsize; Använder alla tecken i nyckeln. Ger en relativt bra distribution. Har fördelen att vara extremt enkel och snabb. Om inte nycklarna är mycket långa. Kollisionshanteringen 7-8 Det finns flera metoder. Vi kommer att presentera två av de enklaste: öppen hashning.» (open hashing, separate chaining) sluten hashning.» (closed hashing, open addressing, rehashing)

Sid 5 Öppen hashning (separate chaining). 7-9 Vid öppen hashning håller man alla element som hashar till samma värde i en separat lista. fördelar: cellerna behöver inte ligga kontinuerligt i minnet. tillåter traversering i hash-key-ordning, dock ej i sekventiell key-ordning. nackdelar: allokeringen av nya celler tenderar att göra denna metod mindre tidseffektiv. kräver att ytterligare en datastruktur implementeras. extra utrymme behövs för hashtabellen och pekarna. Fyllnadsgraden 7-10 Fyllnadsgraden (load factor) lf definieras som antal element i hashtabellen dividerat med tabellstorleken. De intressantaste måtten är den genomsnittlig tiden för: insättning. (lyckad) sökning. misslyckad sökning. borttag.

Sid 6 Öppen hashning, fig 1. 7-11 typedef struct list_node * node_ptr; struct list_node element_type element; node_ptr next; ; typedef node_ptr LIST; typedef node_ptr position; struct hash_tbl unsigned int table_size; LIST *the_lists; // fält av listor, allokeras // senare ;//Listorna använder headers, allokeras senare typedef struct hash_tbl * HASH_TABLE; Öppen hashning, fig 2. 7-12 HASH_TABLE initialize_table( unsigned int table_size ) HASH_TABLE H; int i; H= new struct hash_tbl; /* Allokera tabell */ if( H == NULL ) fatal_error("out of space!!!"); H->table_size=next_prime(table_size); H->the_lists= new LIST[H->table_size]; //Allok list-pek if( H->the_lists==NULL ) fatal_error("out of space!"); for(i=0; i<h->table_size; i++ ) // Allok list-headers H->the_lists[i] = new struct list_node; if( H->the_lists[i] == NULL ) fatal_error("out of space!!!"); else H->the_lists[i]->next = NULL; return H;

Sid 7 Öppen hashning, fig 3. 7-13 position find( element_type key, HASH_TABLE H ) position p; LIST L; L = H->the_lists[ hash(key, H->table_size) ]; p = L->next; while( (p!= NULL) && (p->element!= key) ) // strcmp behövs; p = p->next; return p; Öppen hashning, fig 4. 7-14 void insert( element_type key, HASH_TABLE H ) position pos, new_cell; LIST L; pos = find( key, H ); if( pos == NULL ) // key ej funnen new_cell = new sizeof (struct list_node); if( new_cell == NULL ) fatal_error( "Out of space!!!"); else L= H->the_lists[ hash(key,h->table_size ) ]; new_cell->next = L->next; new_cell->element = key; // strcpy behövs!! L->next = new_cell;

Sid 8 Sluten hashning (rehashing). 7-15 Sluten hashning är ett alternativ för att lösa kollisionsproblemet utan att använda länkade listor. kallas även öppen adressering. Vid sluten hashning prövas alternativa celler tills en ledig hittas. Formell beskrivning:» cellerna h 0 (x), h 1 (x), h 2 (x),... prövas efter varandra där h i (x)= ( Hash(x) + f(i) ) mod hsize,» med f(0)=0. Funktionen f representerar kollisionshanterings-strategin. Sluten hashning (rehashing), forts. 7-16 Alla data ligger i tabellen varför sluten hashning kräver en större tabell än öppen hashning. Generellt bör fyllnadsgraden (lf) vara mindre än 0.5 vid sluten hashning. Kräver lazy deletion. Vi tittar nu närmare på tre olika strategier för kollisionshanteringen: Linjär prövning (Linear probing). Kvadratisk prövning (Quadratic probing). Dubbel hashning (Double hashing).

Sid 9 Linjär prövning. 7-17 f(i) är en linjär funktion, vanligen f(i)=i. Denna innebär att cellerna provas i sekvens. en ledig cell kan alltid hittas så länge som tabellen är tillräckligt stor, men tiden för att göra det kan bli ganska stor. Problem: primär klustring (primary clustering), d v s att block av ockuperade börjar att formas, även om tabellen är relativt tom.» medför att varje nyckel som hashas in i klustret kommer att kräva flera försök för att lösa kollisionerna, och dessutom själv adderas till klustret. Förväntade antalet prövningar är omkring ½( 1 + 1/(1- lf) 2 ) för insättningar och misslyckade sökningar. omkring ½( 1 + 1/(1- lf) ) för lyckade sökningar. Kvadratisk prövning. 7-18 Eliminerar de problem med primär klustring som linjär prövning uppvisar. Dock kvarstår att element som hashar till samma position kommer att pröva samma alternativa celler. Detta är känt som sekundär klustring. Sekundär klustring är mer av teoretiskt intresse. Simuleringar visar att den i allmänhet orsakar en extra halv prövning per sökning. Kollisionsfunktionen är kvadratisk, t ex f(i)= i 2. Sats: Om kvadratisk prövning används och tabellstorleken är ett primtal, kan ett nytt element alltid sättas in om tabellen är åtminstone halvtom.

Sid 10 Sluten hashning, fig 1. 7-19 enum kind_of_entry legitimate, empty, deleted ; struct hash_entry element_type element; enum kind_of_entry info; ; typedef INDEX position; typedef struct hash_entry cell; struct hash_tbl unsigned int table_size; cell * the_cells; // fält av hash_entry celler // allokeras senare ; typedef struct hash_tbl * HASH_TABLE; Sluten hashning, fig 2. 7-20 HASH_TABLE initialize_table( unsigned int table_size ) HASH_TABLE H; int i; if( table_size < MIN_TABLE_SIZE ) error("table size too small"); return NULL; H = new struct hash_tbl; // Allokera tabell if( H == NULL ) fatal_error("out of space!!!"); H->table_size= next_prime( table_size ); // Allok celler H->the_cells = new cell [H->table_size]; if(h->the_cells == NULL) fatal_error("out of space!!!"); for(i=0; i<h->table_size; i++ ) H->the_cells[i].info = empty; return H;

Sid 11 Sluten hashning, fig 3. 7-21 position find( element_type key, HASH_TABLE H ) position i, current_pos; i=0; current_pos = hash( key, H->table_size ); while( (H->the_cells[current_pos].element!= key) && (H->the_cells[current_pos].info!= empty )) // strcpy behövs troligen!! current_pos += 2*(++i) - 1; if( current_pos > H->table_size ) current_pos -= H->table_size; return current_pos; Sluten hashning, fig 4. 7-22 void insert( element_type key, HASH_TABLE H ) position pos; pos = find( key, H ); if( H->the_cells[pos].info!= legitimate ) // ok att göra insert här H->the_cells[pos].info = legitimate; H->the_cells[pos].element = key; // strcpy behövs troligen!!

Sid 12 Dubbel hashning. 7-23 Denna teknik eliminerar problemet med sekundär klustring till priset av extra multiplikationer och divisioner. Dubbel hashning innebär att vi applicerar en andra hash-funktion på x och prövar på distansen hash 2 (x), 2*hash 2 (x),... o s v. Ett populärt val av funktion är f(i)= i * hash 2 (x). Notera att :» funktionen får aldrig evaluera till 0.» viktigt att försäkra sig om att alla celler kan prövas.» ett dåligt val av hash 2 (x) är förödande. Dubbel hashning, forts. 7-24 En funktion som hash 2 (x)= R - (x mod R),» med R som ett primtal mindre än hsize. Simuleringar visar att det förväntade antalet prövningar är nästan detsamma som för en strategi med slumpmässig kollisionshantering. Detta gör dubbelhashning teoretiskt intressant. Kvadratisk prövning kräver dock inte en andra hashfunktion och är således troligen enklare och snabbare i praktiken.

Sid 13 Reorganisation av hashtabellen. 7-25 Om tabellen blir för full kommer Körtiden för de olika operationerna att börja ta för lång tid. Insättningar kanske misslyckas för sluten hashning med kvadratisk lösning (resolution).» Detta kan hända om det är för många borttagningar blandade med insättningarna. En lösning är då att» skapa en ny, dubbelt så stor, tabell (med en ny hashfunktion).» scanna igenom hela den första tabellen under det att nya hashvärden beräknas för varje kvarvarande element och detta sätts in i den nya tabellen. Hela denna operation kallas reorganisation av hashtabellen. Även rehashing används. Detta är uppenbart en mycket dyr operation, som lyckligtvis inträffar relativt sällan. Reorganisation, forts. 7-26 Reorganisation kan implementeras på flera sätt med kvadratisk prövning. Några av alternativen är att göra en reorganisation, 1. så snart som tabellen är halvfull. 2. bara när en insättning misslyckas. 3. så snart som tabellen når en viss fyllnadsgrad.

Sid 14 Reorganisation, fig 1. 7-27 HASH_TABLE rehash( HASH_TABLE H ) unsigned int i, old_size; cell *old_cells; old_cells = H->the_cells; old_size = H->table_size; // Skapa en ny tom tabell H = initialize_table( 2*old_size ); //Scanna igenom den gamla tabellen, och sätt in i den nya. for( i=0; i<old_size;i++ ) if( old_cells[i].info == legitimate ) insert( old_cells[i].element, H ); free( old_cells ); return H; Applikationer - Hashtabell 7-28 Kompilatorer använder hashtabeller för att hålla reda på deklarerade variabler i källkoden (symboltabell). Används i grafteoretiska problem där noderna har namn i stället för nummer. Används i program som spelar något slags spel. När programmet söker igenom olika spellinjer, håller det reda på de ställningar det har sett genom att beräkna en hashfunktion baserad på positionen. Om samma position uppträder igen så kan programmet undvika en dyr ny beräkning.» Denna generella egenskap hos alla spel-program är känd som en transpositionstabell. Ännu ett användningsområde är on-line - stavningskontroll.» Om felstavningsupptäckt är viktig, kan en hel ordbok vara pre-hashad.

Sid 15 Summering 7-29 Hashtabeller kan användas för att implementera insert- och findoperationerna på konstant tid i genomsnitt. Fyllnadsgraden är speciellt viktig att beakta när man använder hashtabeller, eftersom tidsgränserna annars inte gäller. Val av hashfunktion är viktig,» speciellt när nycklarna inte är en kort sträng eller ett heltal. Vid öppen hashning bör fyllnadsgraden vara nära 1,» även om performance inte signifikant degraderas förrän fyllnadsgraden blir mycket hög. Vid sluten hashning bör fyllnadsgraden inte överstiga 0.5. Trots den uppenbara enkelheten hos hashtabellen är mycket av analysen ganska komplicerad och fortfarande återstår många obesvarade frågor. Summering, forts. 7-30 Reorganisation kan implementeras för att tillåta tabellen att växa (och minska) och på så sätt upprätthålla en rimlig fyllnadsgrad. En nackdel med hashtabellen är att den inte understödjer ordnande operationer.» T ex ej möjligt att finna det minsta elementet.» Ej heller möjligt att söka effektivt efter en sträng om inte den exakta strängen är känd. Binära sökträd kan också användas för att implementera insert- och findoperationerna. Binära sökträd stödjer också rutiner som kräver ordning och är således mer kraftfulla. Å andra sidan är värsta fallet för hashning normalt resultatet av ett implementationsfel, medan däremot en redan sorterad indatamängd kan ge ett binärt sökträdett sämre uppträdande.

Sid 16 Slutord. 7-31 Balanserade sökträd är relativt dyra att implementera... Så om ingen ordningsinformation efterfrågas och det finns en antydan till misstanke om att indata redan kan vara sorterat, är hashtabellen den datastruktur som bör väljas.