O(log n) - søk. Søking i et balansert søketre med n elementer er alltid O(log n) Søkingen er basert på parvise sammenligninger av to og to verdier

Like dokumenter
Hashing: Håndtering av kollisjoner

Hashfunksjoner. Hashfunksjonen beregner en indeks i hashtabellen basert på nøkkelverdien som vi søker etter

O(1) søking? Søking i sortert array og i søketrær: Optimalt søk som er O(1):

INF1020 Algoritmer og datastrukturer

Hashing. INF Algoritmer og datastrukturer HASHING. Hashtabeller

... HASHING. Hashing. Hashtabeller. hash(x)

INF2220: Forelesning 3

Maps og Hashing. INF Algoritmer og datastrukturer. Map - ADT. Map vs Array

INF2220: Forelesning 3. Map og hashing Abstrakte datatyper (kapittel 3.1) Map (kapittel 4.8) Hashing (kapittel 5)

Maps og Hashing. INF Algoritmer og datastrukturer. Map - ADT. Map vs Array

INF Algoritmer og datastrukturer

Søkeproblemet. Gitt en datastruktur med n elementer: Finnes et bestemt element (eller en bestemt verdi) x lagret i datastrukturen eller ikke?

Datastrukturer for rask søking

EKSAMEN. Dato: 28. mai 2018 Eksamenstid: 09:00 13:00

Hashtabeller. Lars Vidar Magnusson Kapittel 11 Direkte adressering Hashtabeller Chaining Åpen-adressering

Kapittel 14, Hashing. Tema. Definere hashing Studere ulike hashfunksjoner Studere kollisjonsproblemet 17-1

... Når internminnet blir for lite. Dagens plan: Løsning: Utvidbar hashing. hash(x) katalog. O modellen er ikke lenger gyldig ved

INF2220: Forelesning 3

INF1010 Hashing. Marit Nybakken 8. mars 2004

Obligatorisk oppgave 1 INF1020 h2005

Definisjon: Et sortert tre

Hvor raskt klarer vi å sortere?

INF2220: Forelesning 2

Ny/utsatt EKSAMEN. Dato: 6. januar 2017 Eksamenstid: 09:00 13:00

Flerveis søketrær og B-trær

Definisjon av binært søketre

Sorteringsproblemet. Gitt en array A med n elementer som kan sammenlignes med hverandre:

Liste som abstrakt konsept/datatype

Repetisjon: Binære. Dagens plan: Rød-svarte trær. Oppgave (N + 1)!

Heap og prioritetskø. Marjory the Trash Heap fra Fraggle Rock

Hva er en liste? Hvert element har en forgjenger, unntatt første element i listen. Hvert element har en etterfølger, unntatt siste element i listen

Alg. Dat. Øvingsforelesning 3. Grafer, BFS, DFS og hashing. Børge Rødsjø

Binære trær: Noen algoritmer og anvendelser

EKSAMEN. Dato: 9. mai 2016 Eksamenstid: 09:00 13:00

Definisjon. I et binært tre har hver node enten 0, 1 eller 2 barn

Heap* En heap er et komplett binært tre: En heap er også et monotont binært tre:

Hva er en liste? Hvert element har en forgjenger, unntatt første element i listen. Hvert element har en etterfølger, unntatt siste element i listen

Alg. Dat. Øvingsforelesning 3. Grafer, BFS, DFS og hashing

INF2220: Forelesning 2

INF2220: Forelesning 2. Balanserte søketrær Rød-svarte trær (kapittel12.2) B-trær (kapittel 4.7)

EKSAMENSOPPGAVE. INF-1101 Datastrukturer og algoritmer. Adm.bygget, rom K1.04 og B154 Ingen

TDT4105 Informasjonsteknologi, grunnkurs

Notater til INF2220 Eksamen

Binær heap. En heap er et komplett binært tre:

Hva er en kø? En lineær datastruktur der vi til enhver tid kun har tilgang til elementet som ble lagt inn først

Ordliste. Obligatorisk oppgave 1 - Inf 1020

Algoritmer og Datastrukturer IAI 21899

public interface Collec>on<V> { public void add(v value); public default V remove(v value) { return null;

Datastrukturer. Algoritmer og datastrukturer. Øvingsforelesning 2

Ny/utsatt EKSAMEN. Dato: 5. januar 2018 Eksamenstid: 09:00 13:00

Backtracking som løsningsmetode

Hva er en kø? En lineær datastruktur der vi til enhver tid kun har tilgang til elementet som ble lagt inn først

7) Radix-sortering sekvensielt kode og effekten av cache

UNIVERSITETET. Indeksering. Konvensjonelle indekser B-trær og hashing Flerdimensjonale indekser Hashliknende strukturer.

EKSAMENSOPPGAVE. IAI20102 Algoritmer og datastrukturer

Fra Kap.10 Binære søketre (BS-tre) Sist oppdatert Definere en abstrakt datastruktur binært søketre. Vise hvordan binær søketre kan brukes

Algoritmer og Datastrukturer

Oppgavesettet består av 7 sider, inkludert denne forsiden. Kontroll& at oppgaven er komplett før du begynner å besvare spørsmålene.

Hva er en kø? En lineær datastruktur der vi til enhver tid kun har tilgang til elementet som ble lagt inn først

Hvorfor sortering og søking? Søking og sortering. Binære søketrær. Ordnet innsetting forbereder for mer effektiv søking og sortering INF1010 INF1010

Søking i strenger. Prefiks-søking Naiv algoritme Knuth-Morris-Pratt-algoritmen Suffiks-søking Boyer-Moore-algoritmen Hash-basert Karp-Rabin-algoritmen

NITH PG4200 Algoritmer og datastrukturer Løsningsforslag Eksamen 4.juni 2013

Selv-balanserende søketrær

Øvingsforelesning 2 - TDT4120. Grafer og hashing. Benjamin Bjørnseth

INF Algoritmer og datastrukturer

Turingmaskiner.

INF1010 LISTER. Listeelementer og listeoperasjoner. Foran. Bak

Generelle Tips. INF Algoritmer og datastrukturer. Åpen og Lukket Hashing. Hashfunksjoner. Du blir bedømt etter hva du viser at du kan

Konvertering mellom tallsystemer

Et eksempel: Åtterspillet

Norsk informatikkolympiade runde

Eksamen iin115 og IN110, 15. mai 1997 Side 2 Oppgave 1 Trær 55 % Vi skal i denne oppgaven se på en form for søkestrukturer som er spesielt godt egnet

INF1010 notat: Binærsøking og quicksort

Binære søketrær. Et notat for INF1010 Stein Michael Storleer 16. mai 2013

Kap 9 Tre Sist oppdatert 15.03

Rekursiv programmering

Et eksempel: Åtterspillet

Lars Vidar Magnusson

INF2220: Time 4 - Heap, Huffmann

Stack. En enkel, lineær datastruktur

INF2220: Time 12 - Sortering

Høgskolen i Gjøvik. Avdeling for elektro- og allmennfag K O N T I N U A S J O N S E K S A M E N. EKSAMENSDATO: 11. august 1995 TID:

EKSAMEN. Dato: 18. mai 2017 Eksamenstid: 09:00 13:00

PG4200 Algoritmer og datastrukturer Forelesning 9

Binære søketrær. En ordnet datastruktur med raske oppslag. Sigmund Hansen

Alle hele tall g > 1 kan være grunntall i et tallsystem.

EKSAMEN. Emne: Algoritmer og datastrukturer

Alle hele tall g > 1 kan være grunntall i et tallsystem.

Løsningsforslag for Obligatorisk Oppgave 3. Algoritmer og Datastrukturer ITF20006

UNIVERSITETET. Indeksering. Hvordan finne et element raskt? Vera Goebel, Ellen Munthe-Kaas

INF2220: Forelesning 1. Praktisk informasjon Analyse av algoritmer (kapittel 2) (Binær)trær (kapittel )

Dictionary er et objekt som lagrer en samling av data. Minner litt om lister men har klare forskjeller:

INF 4130 / / Dagens foiler hovedsakelig laget av Petter Kristiansen Foreleser Stein Krogdahl Obliger:

Backtracking som løsningsmetode

Algoritmeanalyse. (og litt om datastrukturer)

Logaritmiske sorteringsalgoritmer

UNIVERSITETET I OSLO. Indeksering. Hvordan finne et element raskt? Institutt for Informatikk. INF Ellen Munthe-Kaas

Python: Rekursjon (og programmering av algoritmer) Python-bok: Kapittel 12 + teoribok om Algoritmer

Sortering i Lineær Tid

UNIVERSITETET I OSLO

Transkript:

Hashing

O(log n) - søk Søking i et balansert søketre med n elementer er alltid O(log n) Søkingen er basert på parvise sammenligninger av to og to verdier Er svært raskt uansett hvor stort søketreet er, fordi logaritmen vokser meget langsomt......men vil allikevel gi lengre søketider for voksende n Kan vi klare å lage en datastruktur som har samme effektivitet uansett hvor stor n er?

O(1) søking? O(1) - søking: Uavhengig av antall elementer Finn verdien med bare ett direkte oppslag i datastrukturen Er praktisk mulig bare hvis vi har en nummerering av alle mulige elementer som kan lagres i datastrukturen, og vi vet hvor hvert element ligger Eksempel: Data om alle personer i Norge, lagret i en array der indeksen til data om hver person er personnummeret

Hashing: Et forsøk på O(1) effektivitet Alle dataene lagres i en lang array med «nok plass», en hashtabell (aka «buckets») Hvert element som lagres har en nøkkelverdi Ut i fra nøkkelverdien beregnes hvilken indeks i hashtabellen som et element skal ligge på Indeksen beregnes med en hashfunksjon Indeksen som beregnes kalles en hashverdi Hvis alle hashverdier som beregnes er ulike, har alle elementer en unik indeks søking blir O(1)!

Typiske anvendelser av hashing Databasesystemer Minnehåndtering i operativsystemer Håndtering av variabler og metoder i kompilatorer Rask gjenfinning av grafikkelementer i 3D-spill Stavekontroll i editorer og tekstbehandlere: Riktig stavede ord kan legges i en hashtabell i stedet for å sorteres alfabetisk i et søketre

Hashing: Eksempel Skal lage et register for maksimalt 1000 objekter Unike nøkkelverdier: Syvsifret tall, f.eks. 4618996 Kan bruke en array med 10 mill. elementer, men... Bruker en array med lengde 1000 (hashlengden) Tre siste sifre i nøkkelverdi brukes som hashverdi: hash(key) = key % 1000 hash(4618996) = 996 (lagres på indeks 996) Og da er alt i orden og vi har en O(1) struktur?

Problem: Kollisjoner Kollisjon*: To elementer får samme indeks Eksempel: hash(key) = key % 1000 hash(6894331) = 331 hash(7462331) = 331 Hashing kan bli O(n) hvis det er mange kollisjoner i hashtabellen! *: Aka «hash-clash»

Og kollisjoner skjer «hele tiden» «En ulykke skjer sjelden alene» «Alt» har en tendens til å opptre i klynger/clustere: Byer, bilkøer, industriklynger, sosiale samlinger Fornavn Maurtuer, fiskestimer, gresshoppesvermer Galakser, stjernehoper Hvorfor det alltid er slik vet vi egentlig ikke, men: Det skal «veldig lite til» før ting begynner å kollidere Klassisk eksempel: Fødselsdagsparadokset

Hashing, kollisjoner og effektivitet Det er alltid mange kollisjoner i hashing med store datamengder For at hashing skal være effektivt må: Hashfunksjonen som brukes gi et lite antall kollisjoner og spre dataene godt i hashtabellen Kollisjoner håndteres så effektivt som mulig Hvis disse to kravene tilfredsstilles, kan hashing være mer effektivt enn både søketrær og B-trær for svært store datamengder

Hashfunksjoner Hashfunksjonen beregner en indeks i hashtabellen basert på nøkkelverdien som vi søker etter Hash: «Kutte opp i biter og blande sammen» Perfekt hashfunksjon: Lager aldri kollisjoner Alle elementer får en unik indeks Kan bare lages i tilfeller der alle data er kjent

Effektive hashfunksjoner Krav til en effektiv hashfunksjon: Beregning av hashverdien må være rask og O(1) Sprer hashverdiene jevnt i hashtabellen Gir et lite antall kollisjoner Utvikling av effektive hashfunksjoner er ikke en «eksakt vitenskap»: Antall kollisjoner avhenger både av datasettet og av lengden på hashtabellen Baserer seg i stor grad på heuristikk og empiri

Hashfunksjoner og hashlengde Hashlengde: Antall elementer i hashtabellen Hashfunksjonen beregner en indeks i hashtabellen: Verdien som returneres må være større eller lik 0 (null) og mindre enn hashlengden Beregner en verdi h basert på nøkkelverdien Returnerer resten ved heltallsdivisjon av h med hashlengden: h % hashlengde Vi vil alltid få bedre spredning og færre kollisjoner hvis hashlengden er et primtall: F.eks. er 997 og 1009 bedre hashlengder enn 1000

Noen typer hashfunksjoner Avkorting Sammenslåing / Folding Midten-av-kvadratet Bytte av tallsystem Utplukk og ombytting Basert på lengde av nøkkelverdi

Hashfunksjon: Avkorting (truncation) «Klipper» bare ut en del av nøkkelverdien Eksempel, nøkkelverdi er en streng: Bruk de k første bokstavene, tolket som siffer Eksempel, nøkkelverdi er et heltall: Bruk de k siste sifferne Finnes med heltallsdivisjon: nøkkelverdi % 10 k Fordel: Rask beregning av hashverdi Ulempe: Fordeler ujevnt, gir mye kollisjoner i tabellen

Eksempel: Hashing med enkel avkorting hashlengde = 8 hash(key) = key % hashlengde hash(36) = 36 % 8 = 4 hash(18) = 18 % 8 = 2 hash(72) = 72 % 8 = 0 hash(43) = 43 % 8 = 3 hash(6) = 6 % 8 = 6 0 72 1 2 18 3 43 4 36 5 6 6 7

Hashfunksjon: Sammenslåing / Folding Del opp nøkkelverdien i flere «småbiter» Slå sammen «småbitene», med f.eks. aritmetiske operasjoner, til en hashverdi Eksempel: Nøkkelverdi: 625381194 Lengde av hashtabell (hashlengde) 1000 Hashverdi: (625 + 381 + 194) % 1000 = 100 Folding sprer bedre enn avkorting

Enkel folding av tekststrenger int hash(string S) { int h = 0; for (int i = 0; i < S.length(); i++) h += (int)(s.charat(i)); return h % hashlengde; } Noen verdier med hashlengde = 1009 : hash("vw Karmann Ghia") = 317 hash("porsche 356A") = 979 hash("alfa Romeo Spider") = 556 hash("renault Floride") = 463

Problem: Enkel folding sprer dårlig I eksemplet på forrige side vil de fleste hashverdiene havne i et relativt lite intervall noen hundre opp til et par tusen for tekst-strenger av begrenset lengde Ubrukelig for store datasett med millioner av data For å spre bedre kan vektet folding brukes: Gi tegnene en vekt basert på posisjon Tolker strengen noe tilsvarende som et desimalt tall, der hvert tegn er et siffer som angir antallet av en potens av 10

Eksempel: Vektet folding av tekststrenger Tolk f.eks. 4 og 4 tegn i strengen som «desimale tall»: VW_Karmann_Ghia Beregn: ((V + W*10 + _*100 + K*1000) + (a + r*10 + m*100 + a*1000) + (n + n*10 + _*100 + G*1000) + (h + i*10 + a*100)) % hashlengde Gir mye større spenn i verdiene som beregnes

Kode: Vektet folding av tekststrenger int hash(string S) { int h = 0, i = 0; while (i < S.length()) { int potens = 1; for (int j = 0; (j < 4 && i < S.length()); j++) { h += (int)(s.charat(i)) * potens; potens *= 10; i++; } } return h % hashlengde; }

Javas egen hashfunksjon for strenger Merk: String.hashCode() ignorerer overflow og kan returnere negative verdier(!)

Hashfunksjon: Midten-av-kvadratet Anta nøkkelverdien er et heltall* Beregn kvadratet av nøkkelverdien Hashverdi: Siffere i midten av kvadratet Eksempel: Bruker hashverdier med tre sifre (000-999) Nøkkelverdi: 18562 18562 18562 = 344547844 hash(18562) = 547 *: For ikke-numeriske nøkkelverdier kan vi bare tolke bitsekvensene som tall

Hashfunksjon: Bytte av tallsystem* Antar nøkkelverdi er et desimalt heltall: Grunntallet er 10, sifferne er 0, 1, 2, 3,..., 8, 9 1369 = 1369 10 = 9 + 6 10 1 + 3 10 2 + 1 10 3 Skriver om nøkkelverdien til f.eks. 8-tallsystemet: Grunntallet er 8, sifferne er 0, 1, 2, 3, 4, 5, 6, 7 2531 8 = 1 + 3 8 1 + 5 8 2 + 2 8 3 = 1369 10 Hvis hashlengden er 1009: hash(1369) = 2531 % 1009 = 513 *: Det finnes flere metoder for bytte av tallsystemer i Java, se f.eks. Integer.toOctalString

Hashfunksjon: Utplukk og ombytting Plukker ut noen siffer eller tegn fra nøkkelverdien Bytter deretter om på disse sifferne/tegnene Eksempel: Vil ha fire-sifrede hashverdier Nøkkelverdier med tolv siffer: 783248695301 Tar ut siffer nummer tre, seks, ni og tolv: 3851 Hashverdi: En eller annen omstokking av sifferne: Reversering: 1583 Høyreskift: 1385 Venstreskift: 8513 Parvis bytting: 8315

Hashfunksjon: Basert på lengde av nøkkelverdi Beregner en hashverdi basert på en nøkkelverdi og nøkkelverdiens lengde Eksempel: Nøkkelverdier med åtte siffer: 46286947 Ganger de tre første sifrene med lengden av nøkkelverdiene: 462 8 = 3696 Deler på det siste sifferet: 3696 / 7 = 528 hashverdi = 528 % hashlengde

Test av ulike hashfunksjoner Enkelt testprogram: hashfunctions.java Tester følgende metoder ved å telle antall kollisjoner: 1. Enkel folding 2. Vektet folding 3. Javas innebygde hashfunksjon (vektet folding) 4. Midten-av-kvadrat 5. Bytte av tallsystem 6. Utplukk og bytting 7. Lengde av dataverdi Hasher hele linjer med tekst fra standard input Testdatasett: cars.txt

Innsetting av dataelement i hashtabell Algoritme: 1. Bruk en hashfunksjon til å beregne hashverdi basert på dataelementets nøkkelverdi 2. Sett inn dataelementet i hashtabellen Innsetting i hashtabell er O(1) hvis problemet med kollisjoner kan løses med en O(1) operasjon Innsetting blir langsommere enn O(1) når hashtabellen blir «for full» av data og det blir mange kollisjoner

Load factor Hashing er svært effektivt så lenge hashtabellen har «mange ledige plasser» og det er lite kollisjoner «Load factor» L er et mål på hvor full en hashtabell er L = n / h n: Antall elementer lagret i hashtabellen h: hashlengden Tolking av load factor: L = 0.5 Halvfull hashtabell L < 1.0 L > 1.0 Færre datalelementer enn arrayplasser Flere datalelementer enn arrayplasser

To metoder for håndtering av kollisjoner Åpen adressering (open adressing): Hvis en indeks i hash-tabellen er opptatt, legges elementet et annet sted i tabellen på en eller annen systematisk måte (f.eks. neste ledige) Load factor maks 1.0 Kjeding (chaining): Hvert element i hash-tabellen er en lenket liste (eller et søketre?) som inneholder alle elementer med samme hashverdi Load factor kan være større enn 1.0

Åpen adressering Hvis hashindeksen som beregnes er opptatt, gjør vi en «probing» (et søk) etter en annen ledig indeks i hashtabellen der vi kan legge elementet Probingen må være systematisk/deterministisk, slik at vi kan finne igjen elementet ved søking Må kunne håndtere muligheten for at vi ikke finner noen ledig plass i tabellen på en robust måte

Enkleste variant av åpen adressering: Lineær probing Beregn dataelementets hashverdi h Hvis indeks h i hashtabellen er opptatt: Sett inn nytt dataelement på første ledige indeks etter indeks h Hvis indeks h + 1 er opptatt, prøv å sette inn på indeks h + 2, h + 3, h + 4, osv., inntil en ledig plass er funnet Gjør en «wrap-around» (fortsett med indeks 0) hvis vi kommer til slutten av tabellen

Lineær probing: Eksempel

Fordeler med lineær probing Enkelt å programmere: hashlinear.java Svært rask beregning av probes (kun én addisjon) Det kan bevises at: Hvis dataene som settes inn er «rimelig tilfeldige» og load factor er 0.5 (maks. halvfull hashtabell), vil lineær probing alltid gi hashtabeller med O(1) effektivitet

Problemer med lineær probing Lite effektiv håndtering av clustering / klumping: Sprer ikke data som hashes til samme område i hashtabellen «primary clustering» Alle elementer som har samme hashverdi vil bli liggende i en «klump» i tabellen Innsetting og søking lite effektivt når tabellen er full: Lineær probing får problemer for load factor > 0.7 Får lange «opptatte sekvenser» i tabellen som må gås gjennom for å finne en ledig plass

Åpen adressering med kvadratisk probing Beregn dataelementets hashverdi h Hvis indeks h i hashtabellen er opptatt: Forsøk å sette inn på indeks h + 1 Hvis indeks h + 1 er opptatt, prøv å sette inn på indeksene: h + 4, h + 9, h + 16, h + 25, h + 36, osv., inntil en ledig plass finnes Gjør en «wrap-around» (fortsett med indeks 0) hvis vi havner utenfor hashtabellen

Kvadratisk probing: Eksempel

Fordeler med kvadratisk probing Enkelt å programmere: hashquadratic.java Sprer elementene bedre enn lineær probing Løser opp «primary clustering» ved å flytte elementer med lik hashverdi langt fra hverandre Det kan bevises at: Hvis load factor er 0.5 og hashlengden er et primtall, vil kvadratisk probing alltid gi hashtabeller med O(1) effektivitet

Problemer med kvadratisk probing Beregning av kvadratiske «probes» er mer kostbart enn lineære Løser ikke opp «secondary clusters»: Elementer som har hashverdier som ligger nære hverandre i hashtabellen, vil i liten grad spres Matematisk analyse av kvadratisk probing er vanskeligere enn for lineær probing og ikke komplett, de mest brukte løsningene er i stor grad basert på «best practice»

Lineær og kvadratisk probing: Sammenligning av effektivitet av søking Konstant load factor lik 0.9, varierende hashlengder Søk der element ble funnet Søk der element ikke ble funnet

Lineær og kvadratisk probing: Sammenligning av effektivitet av søking Konstant hashlengde lik 1000, varierende load factor Søk der element ble funnet Søk der element ikke ble funnet

Åpen adressering med rehashing Probing med rehashing*: Bruk en annen og anderledes hashfunksjon for å finne neste indeks/probe ved kollisjoner Hvis neste indeks også er opptatt, prøv med f.eks. 2 ganger ny hashverdi, deretter 3 ganger ny verdi etc. Gir ofte bedre spredning enn lineær og kvadratisk probing Kan løse opp både primære og sekundære clustere *: Også kalt «dataavhengig probing»

Åpen adressering med bruk av en randomgenerator Probing med en (pseudo) randomgenerator: Hvis kollisjon, bruk hashverdien som seed i en randomgenerator og beregn nye indekser som en sekvens av «tilfeldige» tall (% hashlengde) inntil ledig plass funnet Fungerer fordi alle randomgeneratorer egentlig er deterministiske (pseudo random) og sekvensen av tilfeldige tall kan gjenskapes Kan også gi bedre spredning enn lineær og kvadratisk probing

Når hashtabellen blir full Med åpen adressering bør hashlengden økes når: Load factor blir > 0.8, eller: Vi ikke finner noen ledig indeks ved kollisjoner Vanlig å doble lengden av hashtabellen: Vet at effektiviteten er garantert for load factor < 0.5 Velger alltid hashlengde lik nærmeste primtall Økning av hashlengden er en O(n) operasjon: Alle elementer må hashes på nytt for at de skal kunne finnes igjen med ny hashlengde

Fjerning av elementer fra en hashtabell med åpen adressering Problem: Vi risikerer å «bryte kjeden» ved å fjerne et element som ligger i en liste av probes Vanlig løsning: Ikke fjern elementer, men bruk i stedet en ekstra boolsk array til å merke at elementer skal slettes Ved kollisjoner kan vi stoppe kjeden av probes når vi kommer til et element som er merket som fjernet, og bare overskrive dette elementet Alle elementer som er merket som fjernet, blir tatt vekk hver gang vi må gjøre en fullstendig rehashing i forbindelse med økning av lengden på hastabellen

Hashing med kjeding Hashtabellen er en array av lister (buckets): Vanlig å bruke usorterte lenkede lister Alternativt kan listene «simuleres» ved å legge elementer som kolliderer i et «overflow» område i hashtabellen, for å spare overhead til pekere* Kollisjoner løses enkelt: Alle elementer som får samme hashverdi legges inn i listen som ligger på denne indeksen i hashtabellen Hashing med kjeding partisjonerer dataene opp i små delmengder som kan behandles effektivt *: Se figur E.3 i Appendix E i læreboka

Kjeding: Eksempel

Effektivitet av hashing med kjeding Innsetting og søking krever: Beregning av hashverdi / indeks i hashtabellen Sekvensielt søk i den usorterte listen som ligger lagret på denne indeksen Enkel implementasjon: hashchained.java Hashing med kjeding kan bli O(1) hvis: Hashfunksjonen sprer jevnt, slik at listene blir omtrent like lange Load factor ikke er for stor, slik at listene ikke blir svært lange

Load factor, hashlengde og kjeding Kjeding fungerer også for load factor større enn 1.0, hvis hashfunksjonen sprer jevnt Fra Wikipedia: Chained hash tables remain effective even when the number of table entries n is much higher than the number of slots. Their performance degrades more gracefully (linearly) with the load factor. For example, a chained hash table with 1000 slots and 10,000 stored keys (load factor 10) is five to ten times slower than a 10,000-slot table (load factor 1); but still 1000 times faster than a plain sequential list, and possibly even faster than a balanced search tree.

Effektivitet av kjeding: Test av søking Load factor = 1.0 Varierende hashlengde Fast hashlengde Varierende load factor

Kjeding: Fordeler og ulemper Fordeler: Raskt, sammenligner bare elementer med lik hashverdi Tåler load factor >> 1.0, mindre behov for økning av hashlengde og full rehashing Fjerning av elementer er enkelt (lenket liste) Ulemper: Krever O(n) ekstra plass til referanser/pekere Økning av hashlengde med full rehashing er mer komplisert/tidkrevende enn for åpen adressering, fordi vi må håndtere dynamisk hukommelse/pekere

Sammenligning: Søkealgoritmer og datastrukturer Søkealgoritme Datastruktur Sortert? Innsetting Søking Fjerning Sekvensiell Liste/array Nei O(1) O(n) O(n) Binærsøk Array Ja O(n) O(log n) O(n) Søketre* Binært tre Ja O(log n) O(log n) O(log n) Hashing** Hashtabell Tja O(1) O(1) O(1) *: Garantert oppførsel (AVL) **: Ikke garantert