Innehåll Sökning och hashtabeller Henrik Bergström henrikbe@dsv.su.se Sökning i linjära strukturer Söka efter många objekt Sökning efter ett objekt Sekventiell sökning Binär sökning Sökning efter godtyckligt kriterium Hashning Open-address hashing Chained hashing En bil-klass att söka efter class Bil{ private String marke, regnr; private int mil, year; public Bil(String ma, String r, int mi, int y){ marke=ma; regnr=r; mil=mi; year=y; public String getmarke(){ return marke; public String getregnr(){ return regnr; public int getmil(){ return mil; public int getyear(){ return year; public String tostring(){ return regnr+" "+marke+" från år:"+year; En bilsamling att söka i public ArrayList getall(string sökt){ if (minabilar[x].getmarke().equals(sökt)) Obs: detta är en minimal samling Hitta alla bilar av ett visst märke public ArrayList getall(string sökt){ if (minabilar[x].getmarke().equals(sökt)) Anrop: BilSamling bs = new BilSamling(); // bs fylls med bilar ArrayList volvobilar = bs.getall( Volvo ); Hur hittar vi alla bilar som uppfyller ett annat villkor En metod för varje villkor Skicka med villkoret 1
Att skicka med villkoret - förberedelser public interface Urval{ boolean skaväljas(bil b); public ArrayList getall(urval u){ if (u.skaväljas(minabilar[x])) Att skicka med villkoret - användandet class Val implements BilSamling.Urval{ public boolean skaväljas(bil b){ return b.getyear()==1995 && b.getmil()>3000; Anrop: BilSamling bs = new BilSamling(); // bs fylls med bilar ArrayList resultat = bs.getall(new Val()); Sekventiell sökning Börja från början Kontrollera objekt för objekt Hittar du det sökta elementet - returnera det Har du gått igenom hela listan - returnera null Sekventiell sökning if (minabilar[x].getregnr().equals(regnr)) return minabilar[x]; return null; Binär sökning Mycket snabbare Kräver att objekten är sorterade Kontrollera mittersta elementet Om det är det sökta returnera det Om sökintervallet är tomt så returnera null Annars upprepa med den del av intervallet där det sökta objektet måste finnas Binär sökning public Bil binsearch(string regnr){ int start=0, stop=antal-1, middle; while (start<=stop){ middle=(start+stop)/2; String middlenr=minabilar[middle].getregnr(); int cmp=middlenr.compareto(regnr); if (cmp==0) return minabilar[middle]; else if (cmp<0) start=middle+1; else stop=middle-1; return null; 2
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Objektnyckel=array-index Nr: 2 Nr: 6 Nr: 9 Nr: 14 class Faktura{ int nr; String vem; dubble belopp; // etc... Objektnyckel=array-index Hur gör vi med bilarna? Hashning Hash-funktion beräknar index från objektnyckeln Ska ge slumpmässigt index inom intervallet Index ska bli jämt fördelade inom intervallet Måste anpassas till nyckeln Hashning Nyckeln är ett datum på formen ÅÅMMDD Arrayen består av 1000 positioner Konstruera en hashfunktion Ett första försök Ett andra försök int hash1(int fdat){ return fdat%1000; int hash2(int fdat){ int tal = (fdat%100) * 13 + (fdat/100%100) * 17 + (fdat/10000) * 23; return tal%1000; 3
Hashning av bilar private int hash(string rnr){ int sum=0; for (int x=0; x<rnr.length(); x++) sum+=rnr.charat(x); return sum%100; minabilar[index]=b; Kollisioner OPW923 => index 4 OPW924 WOP392 return minabilar[index]; Jämförelse mellan datumalgoritmerna Open-address hashing 200 180 160 Antal per index alg 1 200 180 160 Antal per index alg 2 OPW923 Vid kollision - sök framåt tills nästa lediga plats. Obs rundgång från 99 till 0. 140 120 140 120 OPW924 100 80 60 40 20 0 0 200 400 600 800 1000 100 80 60 40 20 0 0 200 400 600 800 1000 WOP392 Har index = 4 Ruta 4 upptagen Ruta 5 upptagen Hamnar i ruta 6 Open-address hashing while (minabilar[index]!=null){ index++; if (index==100) index=0; minabilar[index]=b; Chained hashing OPW923 Varje ruta tillåts innehålla flera objekt. En länkad lista med ställföreträdare. while (minabilar[index]!=null &&!minabilar[index].getregnr().equals(regnr)){ index++; if (index==100) index=0; return minabilar[index]; OPW924 WOP392 4
Chained hashing private class Link{ Link next; Bil obj; Link(Link n, Bil o){ next=n; obj=o; private Link[]minaBilar=new Link[100]; private int hash(string rnr){ int sum=0; for (int x=0; x<rnr.length(); x++) sum+=rnr.charat(x); return sum%100; Chained hashing - forts minabilar[index]=new Link(minaBilar[index], b); Link l=minabilar[index]; while (l!=null &&!l.obj.getregnr().equals(regnr)) l=l.next; return l!=null? l.obj : null; 5