INF 295 Algoritmer og datastrukturer
Forelesning 10 Invarianter og Hashing
Hans Fr. Nordhaug
(Ola Bø)
Invarianter
I mange algoritmer er det vilkår som forblir uforandret mens algoritmen kjøres
Slike vilkår kalles invarianter Det er nyttig å kjenne igjen invarianter for å forstå
algoritmen Invarianter kan også brukes under feilsøking For algoritmen som setter inn en ny node i et
søketre er invarianten vilkåret for søketrær, nemlig at for hver node skal alle noder i dens venstre subtre ha lavere verdi og alle noder i dens høyre subtre ha høyere verdi
Invarianter
Invarianten er ikke nødvendigvis sann for hver programsetning, men må stemme for hver gang programmet kommer til et gitt punkt.
Hash-tabell-ADT
Færre operasjoner enn binært søketre Hashing er en teknikk for innsetting, søking
og sletting i konstant tid Men findMin, findMax og printSorted støttes
ikke i lineær tid Hashtabell kan implementeres på ulike måter
Sammenlikning av implementeringer Vise applikasjoner Sammenlikning med binære søketrær
Hash-tabell Array med konstant størrelse Instansene vi søker etter lagres i tabellen Vanligvis blir søk basert på en eller flere
instansvariable Det vi søker på kalles nøkkel Eksempel:
Ansatt(Navn, Adresse, Fødselsnummer,Avd, Lønn,..) TableSize Fra nøkkelen beregnes et bestemt tall mellom 0
og TableSize-1. Dette tallet avgjør hvor instansen lagres
Beregningen er en funksjon - en hash-funksjon
Hash-funksjonen
Indeks=Hash(nøkkel) Bør være enkel (rask) å beregne Bør ideelt plassere instansene i hver sin celle
Vanskelig å oppnå Vi søker funksjoner som gir jevn spredning av nøklene
Hva vi må forholde oss til Hvordan velge hash-funksjonen Hva om to nøkler hashes til samme celle? Hvor stor bør Hash-tabellen være
Hash-funksjoner
Standard hash-funksjon - der nøkkel er heltall Velge primtall som TableSize Hashfunksjonen er resten i divisjonen av nøkkel med
TableSize. (nokkel%tableSize) Vanligvis er nøklene String
Addere ascii (Unicode) verdiene for tegnene og deretter finne resten - ubrukelig
Bruke bokstavverdiene som koeffisienter i et polynom og beregne verdien av polynomet for en gitt x Fungerer dårlig med bare de første bokstavene og x=27 Fungerer bra med alle bokstavene og x=29 Beregningen går fort med Horners regel
Hash-funksjoner
Java String sin Hash-funksjon
Kollisjonshåndtering med separat kjede
Lage liste over alle elementer som hasher til samme celle
Innsetting Finn nøkkel, Gjennomsøk lista, Duplikathåndtering Sett inn nye først - fordi sist innsatt ofte reaksesseres snart
Andre alternativer: trær, ny hash - brukes vanligvis ikke
Lastfaktor λ=elements/TableSize Gjennomsnittlig listelengde=lastfaktoren Regel: Ta sikte på lastfaktor=1 dvs:
TableSize=antatt antall elementer
Kollisjonshåndtering med åpen adressering
Ved kollisjon - prøv neste celle til du finner en ledig.
Hva er neste celle? Avhenger av søkestrategien f(i) hi(x)=(hash(x)+f(i))%TableSize
Alternativ til lenket liste: Kanskje raskere Enkelt med bare én datastruktur
Lastfaktoren må være mindre: λ<0.5
Søkestrategier ved åpen adressering Lineær søking
f(i) er en lineær funksjon. f. eks. f(i)=i Primær clustering av elementer kan føre til kostbare søk
Kvadratisk søking f(i) er en kvadratisk funksjon f. eks. f(i)=i2
Kan svikte totalt hvis λ>0.5 Må ha odde TableSize - ellers kan vi få svikt lenge før λ=0.5 Sekundær Clustering
Dobbel hashing F.eks f(i)=i*hash2(x) NB hash2(x) skal ikke kunne bli 0 Forslag: hash2(x)=R-(x mod R), der R er prim<TableSize
Dekning er viktig
Lineær versus kvadratisk søking
Mer om åpen adressering Sletteproblemet:
Kan ikke slette elementer Rehashing
Ved stor lastefaktor blir hashtabellen lite effektiv eller kan svikte helt (kvadratisk søk)
Løsning: Lag ny, minst dobbelt så stor tabell og hash alle elementene inn i den nye tabellen
Kostbar, men sjelden operasjon Problem hvis del av interaktivt system Når startes det?
Halvfull tabell ved kvadratisk søking Når innsetting mislykkes På en bestem lastefaktor
Anvendelser
Kompilatorer - symboltabeller Spill - transposisjonstabeller Stavekontroll I databaser
Konklusjon
Hashtabell er bedre enn søketre på finn og sett inn Ved mistanke om sorterte inndata bør du absolutt velge Hashtabell -
Hvorfor? Hashtabell er ubrukelig på traversering og findMin Viktige momenter for hashtabeller
Hashfunksjonen må gi god spredning og full dekning med de aktuelle nøklene
TableSize må være primtall Lastfaktoren λ er avgjørende for ytelsen Strategi for kollisjonshåndtering
Åpen adressering er svært følsom for λ og kan få clustering-problemer Kjedet implementering tåler høyere λ, men er kanskje mer komplisert