1 Hashing. 2 Hashing Hashfunktioner Kollisionsstrategier Effektivitet Hashing i Javas biblioteker Prioritetskøer Binær hob Anvendelser: heapsort, ekstern.

Slides:



Advertisements
Lignende præsentationer
Den danske befolknings syn på handicappedes rettigheder
Advertisements

Atomer Et programmeret forløb. En måde at lære på.
1 Ekstern sortering. 2 (sortering på eksterne lagermedier) Særlige hensyn: (1) Det er tidsmæssigt dyrt at tilgå et dataelement (2) Der er begrænsninger.
v/ Professor Lars Ehlers, Aalborg Universitet
Bolig selskabernes Landsforening– Almene lejeboliger - Maj/Juni Almene lejeboliger - Danmarkspanelet - Maj/Juni 2010.
Sortering af affald Dato: 17. december Agenda Sortering af affald Dato: 17. december 2010 TNS Gallup A/S Kontaktperson Celia Paltved-Kaznelson Danmarks.
1 Effektiv forrentning Kjeld Tyllesen PEØ, CBS Erhvervsøkonomi / Managerial Economics Kjeld Tyllesen, PEØ, CBS.
Array vs. ArrayList. Arrays Et array er en struktureret metode til at gemme flere værdier af den samme datatype. Data’en i et array ligger op ad hinanden.
Arbejdsmarkedsuddannelser – også for personer med læse-, skrive- og regnevanskeligheder Oplæg fra AMU-Fyn Konference d. 22/5 -07.
Representations for Path Finding in Planar Environments.
DCS/DTS fællesmøde januar 2010 Denne præsentation har været fremlagt ved DCS / DTS Fællesmøde 2010 og Poul Erik Mortensen har alle rettighederne til gengivelse.
HUSKESPIL – den lille tabel
Titel: Arial, fed, skriftstr. 20, mørkegrå. Tekst: Arial, normal, fed eller kursiv, skriftstr. 10, 12 og 14 til print – 16 og 18 til projektor – mørkegrå.
Relativ vigtighed for elektroniske ressourcer,24,22,20,18,16,14,12,10 Indeks FARM nem at bruge Info om anvendelse af elektroniske.
Begreber og Redskaber 8. Plan for idag Sortering fortsat Comparable Søgning –Lineær søgning –Binær søgning.
 2 3  3 =  83  43  53  63  73  93  10 4.
Søgning & sortering Intro søgning Lineær søgning Binær søgning
GP5, Martin Lillholm 1 Grundlæggende Programmering (GP) Efterår 2005 Forelæsning 5 Slides ligger på nettet. Du er velkommen til at printe dem nu. Vi begynder.
Pleje og Sundhed Gennemførte719 Inviterede895 Svarprocent80% FREDERICIA KOMMUNE MTU og Psykisk APV 2012 Rapportspecifikationer.
1 UNION-FIND. 2 inddata: en følge af heltalspar (p, q); betydning: p er “forbundet med” q uddata: intet, hvis p og q er forbundet, ellers (p, q) Eksempel.
Induktion og rekursion
Region Midtjyllands tilbud 2013
Datastrukturer og Collections Rasmus D. Lehrmann DM
ETU 2008 | Elevtilfredshedsundersøgelse Erhvervsskolen Nordsjælland HTX (Teknisk Gymnasium) - Hillerød Baseret på 313 besvarelser.
Multi-vejs hobe med ekstra bytes Foredrag: Claus Jensen Projektmedlemmer: Jyrki Katajainen, Fabio Vitale, Claus Jensen.
Begreber og Redskaber 5. Collections i Java 1.2 Framework: samling af datastrukturer og algoritmer som generelt værktøj. En ramme til at arbejde med søgning.
Algoritmer og Datastrukturer 1 Merge-Sort [CLRS, kapitel 2.3] Heaps [CLRS, kapitel 6] Gerth Stølting Brodal.
D 3 5A A A 16 5D 15 5A 14 5D A B D D A B A A D
1 Søgning I. 2 Plan Sekventiel søgning Binær søgning Binære søgetræer Balancerede binære søgetræer træer.
Finansiel vurdering af investeringer
1 Sortering I elementære metoder. 2 Plan Terminologi Elementære metoder til sortering -sortering ved udvælgelse -sortering ved indsættelse -Shellsort.
Anvendelser I Leg og spil.
Matematik B 1.
Claus Brabrand, ITU, Denmark Mar 10, 2009EFFECTIVE JAVA Effective Java Presentation Workshop Claus Brabrand [ ] ( “FÅP”: First-year Project.
1 Tråde 2 Plan Trådbegrebet Synkronisering Koordinering Eksempel: et flertrådet spil.
Grunde til at jeg elsker dig
GP 11, 14/ Grundlæggende programmering Efterår 2001 Forelæsning 11 onsdag 14/ kl. 9:15 – 12:00.
1 Søgetræer. 2 Binære søgetræer Definition Operationer Balancerede binære søgetræer AVL-træer Rød-sort-træer (AA-træer) B-træer Plan.
Lektion 7 Læsestof: Kopier fra Caranno
Fundamentale datastrukturer
FEN KbP/seminar2: design11 Kontraktbaseret programmering Seminar 2 Klassedesign – grundprincipper Eksempler: Stack Dictionary.
Design, verifikation og analyse
1 Design, analyse og verifikation. 2 Design Bevisteknikker Design ved hjælp at matematisk induktion Analyse O-notation Logaritmer Binær søgning Verifikation.
1 Sortering. 2 Plan Elementære metoder til sortering -sortering ved indsættelse -Shellsort Sorteringsmetoder baseret på rekursion –quicksort –flettesortering.
Grafalgoritmer II.
1 Sortering II. 2 Plan Avancerede sorteringsmetoder: Metoder med kompleksitet O(n logn): - Quicksort (ekskurs: udvælgelse) - Sortering ved fletning
1 Sortering. 2 Sortering ved fletning (merge-sort) 7 2 | 9 4  | 2  2 79 | 4   72  29  94  4.
10. Datastrukturer. 2 Nordjyllands Erhvervakademi Collections library Datastrukturer i.NET kaldes normalt Collections Findes i namespace System.Collections.
1 Fundamentale datastrukturer. 2 Definitioner: abstrakt datatype, datastruktur Elementære datastrukturer og abstrakte datatyper: arrays, stakke, køer,
1 Fundamentale datastrukturer. 2 Definitioner: abstrakt datatype, datastruktur Elementære datastrukturer og abstrakte datatyper : arrays, stakke, køer,
Begreber og Redskaber 8. Plan for idag Sortering fortsat Comparable Søgning –Lineær søgning –Binær søgning.
1 Søgning II 2 Plan Søgning ved nøgletransformation (hashing) –Hashfunktioner –Kollisionsstrategier –Effektivitet –Hashing i Java ( class HashTable )
1 Kap. 4, Jordens Tyngdefelt = Torge, 2001, Kap. 3. Tyngdekraftens retning og størrelse g (m/s 2 ) Acceleration Tyngdepotentialet (W): evene til at udføre.
1 Sortering. 2 Plan Elementære metoder til sortering -sortering ved indsættelse -Shellsort Sorteringsmetoder baseret på rekursion –quicksort –flettesortering.
KF04 GRAY Item 2, 12, 22, 32, 42, 52. Consider a builder when faced with many constructor parameters Item 2.
Anvendelser I Leg og spil.
Grundlæggende programmering Forår 2002
Begreber og Redskaber 11. Plan for idag Lidt afrunding: Collections Framework i Java Noget om oversættere og sprog Evaluering Sidste gang øvelser før.
Paradigmer i Programmering 3. Højere ordens funktioner Idag: Højere ordens funktioner Algebraiske datatyper Næste gang: I/O, Filer, interaktive programmer.
Effective Java Blå gruppe. Item 18: Interfaces frem for abstrakte klasser Kan implementeres i klasser der ikke nedarver Eksisterende klasser kan nemt.
 Henrik B. Christensen, 1999Introducerende objektorienteret programmering8B.1 Interfaces En ren kontrakt.
Containerklasser – klassifikation og brug.  Michael E. Caspersen, 2003IOOPContainerklasser.2 Mange objekter Containerklasser –antag at man skal repræsentere.
Algoritmer og Datastrukturer 1 Hashing [CLRS, kapitel ]
Algoritmer og Datastrukturer 1
Algoritmer og Datastrukturer 1
Algoritmer og Datastrukturer 1
Præsentationens transcript:

1 Hashing

2 Hashing Hashfunktioner Kollisionsstrategier Effektivitet Hashing i Javas biblioteker Prioritetskøer Binær hob Anvendelser: heapsort, ekstern sortering Plan

3 Hashing søgning ved nøgletransformation Med balancerede træer foretages O(log 2 N) sammenligninger af nøgler. Men er O(log 2 N) den bedst opnåelige kompleksitet? Nej. Hvordan opnås lavere kompleksitet? Med hashing, en teknik, der benytter transformationer af nøgler til direkte at kunne referere til poster i en tabel. Med hashing opnås under gunstige omstændigheder kompleksitet O(1).

4 Grundlæggende ide Ideelt set burde to forskellige nøgler afbildes på to forskellige indices. At to eller flere nøgler afbildes på samme indeks kaldes en kollision. En kollisionsstrategi er en algoritme til håndtering af kollisioner. Gem hver post i en tabel på en plads, der er bestemt af postens nøgle. En hashfunktion er en metode til beregning af et tabelindeks ud fra en nøgle. Matematisk udtrykt: En hashfunktion er en afbildning af en mængde af nøgler på et indeksinterval. h: K I

5 Tid/plads-afvejning (trade off) Ingen pladsbegrænsninger: benyt nøglen som indeks (triviel hashfunktion) Ingen tidsbegrænsninger: benyt sekventiel søgning Hvis der er begrænsninger på både plads og tid: benyt hashing

6 Hashingteknikken Lad h betegne hashfunktionen. Indsættelse: En post med nøgle K placeres på indeks h(K), med mindre der i forvejen er en post på dette indeks. Så må posten placeres på anden måde (hvordan - afhænger af kollisionsstrategien). Søgning: Ved søgning efter en post med nøgle K, undersøges først posten på indeks h(K). Hvis denne indeholder K, afsluttes søgningen med succes. Ellers fortsætter søgningen (hvordan - afhænger af kollisionsstrategien).

7 “Gode” hashfunktioner Kollisioner bør så vidt muligt undgås. Hashfunktionen bør sprede funktionsværdierne jævnt på hele indeksintervallet. Hashfunktionen bør være beregningsmæssigt billig.

8 Konstruktion af hashfunktioner (Korte nøgler) Korte nøgler (nøgler, der kan være i et maskinord): Betragt nøglen som et heltal og beregn h(K) = K mod M (i Java: K % M) hvor M er tabelstørrelsen. h(K) [0;M-1]

9 Nøgler bestående af 4 ascii-tegn, tabelstørrelse 101. ascii a b c d hex bin Eksempel med korte nøgler 0x = % 101 = 11 Nøglen "abcd" hasher til 11. 0x = % 101 = 57 Nøglen "dcba" hasher til 57. 0x = % 101 = 57 Nøglen "abbc" hasher også til 57. Kollision!

10 Konstruktion af hashfunktioner (Lange nøgler) Lange nøgler (nøgler, der ikke kan være i et maskinord): Betragt nøglen som et langt heltal og beregn h(K) = K mod M hvor M er tabelstørrelsen. Altså i princippet som for korte nøgler.

11 Eksempel med lange nøgler Eksempel med 4 tegn. Men metoden virker også for vilkårligt lange nøgler. Benyt Horners regel: 0x = 97* * * = ((97* )* )* Tag modulo efter hver addition for at undgå aritmetisk overløb: (97* = 24930) % 101 = 84 (84* = 21603) % 101 = 90 (90* = 23140) % 101 = 11

12 Tabelstørrelsen Vælg tabelstørrelsen som et primtal. Hvorfor? I eksemplet før havde vi " abcd " = 0x = 97* * * Hvis tabelstørrelsen vælges til 256, vil kun det sidste tegn have betydning ved beregning af h. En simpel måde at sikre sig, at alle tegn bidrager, er at vælge tabelstørrelsen som et primtal.

13 int hash(String key, int tableSize) { int h = 0; for (int i = 0; i < key.length(); i++) h = (h*37 + key.charAt(i)) % tableSize; return h; } Eksempel på hashfunktion For at sprede værdierne bedre er 256 erstattet med 37. Modulo-beregningerne undervejs kan undværes: int hash(String key, int tableSize) { int h = 0; for (int i = 0; i < key.length(); i++) h = h*37 + key.charAt(i); h %= tableSize; return h < 0 ? h + tableSize : h; }

14 public int hashCode() { int h = 0; int off = offset; char val[] = value; int len = count; if (len < 16) { for (int i = len; i > 0; i--) h = (h * 37) + val[off++]; } else { // only sample some characters int skip = len / 8; for (int i = len; i > 0; i -= skip, off += skip) h = (h * 39) + val[off]; } return h; } Javas implementering af hashCode i String (Java 1.1)

15 Javas implementering af hashCode i String (Java 1.2) public int hashCode() { int h = 0; int off = offset; char val[] = value; int len = count; for (int i = 0; i < len; i++) h = 31*h + val[off++]; return h; }

16 Hyppigheden af kollisioner Fødselsdagsparadokset: Hvor mange personer skal være forsamlet i et selskab, for at der er mere en 50% sandsynlighed for at mindst to personer har fødselsdag på samme dato? Svar: 24. Hvis M være tabelstørrelsen, hvor mange indsættelser kan da i gennemsnit foretages, før der opstår en kollision? M

17 Kollisionstrategier Antal poster: N Tabelstørrelse: M Mulighed 1 (separat kædning): Tillad N > M: Læg nøgler, der hasher til samme indeks, ind i en liste (med cirka N/M nøgler per liste). Mulighed 2 (åben adressering): Sørg for at N < M: Læg kolliderende nøgler i tabellen.

18 Separat kædning Simpel, praktisk og meget udbredt metode. Metode: M hægtede lister - en for hver tabelindgang. 0:* 1:L A W * 2:M X * 3:N C * 4:* 5:E P * (M = 11) 6:* (N = 14) 7:G R * 8:H S * 9:I * 10:* Nedbringer den gennemsnitlige søgetid med en faktor M i forhold til sekventiel søgning.

19 Implementering af separat kædning public interface HashTable { void put(Object key, Object value); Object get(Object key); void remove(Object key); } public class SeparateChainingHashTable implements HashTable { private HashEntry[] array;... }

20 class HashEntry { HashEntry(Object k, Object v, HashEntry n) { key = k; value = v; next = n; } Object key, value; HashEntry next; }

21 void put(Object key, Object value) { int pos = Math.abs(key.hashCode()) % array.length; for (HashEntry e = array[pos]; e != null; e = e.next) if (key.equals(e.key)) return; array[pos] = new HashEntry(key, value, array[pos]); } Object get(Object key) { int pos = Math.abs(key.hashCode()) % array.length; for (HashEntry e = array[pos]; e != null; e = e.next) if (key.equals(e.key)) return e.value; return null; }

22 void remove(Object key) { int pos = Math.abs(key.hashCode()) % array.length; for (HashEntry e = array[pos], prev = null; e != null; prev = e, e = e.next) if (key.equals(e.key)) { if (prev != null) prev.next = e.next; else array[pos] = e.next; return; } prevee.next

23 Effektivitet af separat kædning Indsættelse: N/M (i gennemsnit) Mislykket søgning:N/M (i gennemsnit) Succesfuld søgning: 1 + N/M/2 (i gennemsnit) Værste tilfælde: N Hvis listerne holdes sorteret: Tid for mislykket søgning mindskes til N/M/2 Tid for indsættelse øges til N/M/2

24 Åben adressering Lineær prøvning Åben adressering: Ingen hægter. Alle poster opbevares i tabellen. Lineær prøvning: Start lineær søgning fra hashpositionen, og stands ved den søgte post eller en tom position. Stadig konstant søgetid, hvis M er tilstrækkelig stor.

25 Et simpelt eksempel Mængden af nøgler er alfabetets store bogstaver. Der er ingen information tilknyttet nøglerne. Tabelstørrelsen er 7. h(K) = (K’s nummer i alfabetet) mod 7 = (K - ‘A’ + 1) %

26 h(N) = 14 % 7 = 0 h(C) = 3 % 7 = 3 h(K) = 11 % 7 = 4 h(S) = 19 % 7 = C S N K Tabel efter indsættelse af nøglerne C, K, N, S

27 Indsættelse af Y giver kollision h( Y ) = 25 % 7 = C S N K Placering efter 3 forsøg C S N K Y

28 Indsættelse af D h( D ) = 4 % 7 = C S N K Y Placering efter 5 forsøg (med “wrap around”) C S N K Y D Bemærk: tabellen må ikke blive fuld!

29 Implementering af åben adressering abstract class ProbingHashTable implements HashTable { ProbingHashTable() { array = new HashEntry[size]; } void put(Object key, Object value) {... } Object get(Object key) {... } void remove(Object key) {... } abstract protected int findPos(Object key); private HashEntry[] array; private int currentSize; }

30 Object get(Object key) { int pos = findPos(key); if (array[pos] == null || !array[pos].isActive) return null; return array[pos].value; } class HashEntry { HashEntry(Object k, Object v) { key = k; value = v; } Object key, value; boolean isActive = true; } void remove(Object key) { int pos = findPos(key); if (array[pos] == null) return; array[pos].isActive = false; }

31 void put(Object key, Object value) { int pos = findPos(key); array[pos] = new HashEntry(key, value); if (++currentSize < array.length / 2) return; // rehash HashEntry[] oldArray = array; array = new HashEntry[nextPrime(2 * oldArray.length)]; currentSize = 0; for (int i = 0; i < oldArray.length; i++) if (oldArray[i] != null && oldArray[i].IsActive) put(oldArray[i].key, oldArray[i].value); } Tidsforbruget for nextPrime er O( √ N * logN). Ved rehash er simpel kopiering utilstrækkelig.

32 class LinearProbingHashTable extends ProbingHashTable { protected int findPos(Hashable key) { int pos = Math.abs(key.hashCode()) % array.length; while (array[pos] != null && !array[pos].key.equals(key)) pos = (pos + 1) % array.length; return pos; } Klassen LinearProbingHashTable

33 Effektivitet af lineær prøvning Tyndt besat tabel: ligesom separat kædning. Lineær prøvning bruger gennemsnitligt færre end 5 forsøg for en hashtabel, der er mindre end 2/3 fuld. De præcise udtryk er: forsøg ved mislykket søgning, og forsøg ved succesfuld søgning, hvor  = N/M betegner fyldningsgraden.

34 Effektivitetskurver for lineær prøvning Mislykket søgningSuccesfuld søgning  

35 Argumentation for tendens til klyngedannelse Så vil chancen for, at en ny post placeres på position j+1 være lig med chancen for, at en ny post skal placeres i intervallet [i:j+1]. For at den nye post placeres på j+2, skal dens hashværdi derimod være præcis j+2. i-1j+1j+2 Antag at alle positioner [i:j] indeholder poster, mens i-1, j+1 og j+2 er tomme.

36 Klyngedannelse Uheldigt fænomen. Lange klynger har en tendens til at blive længere. Søgelængen vokser drastisk, efterhånden som tabellen fyldes. Lineær prøvning er for langsom, når tabellen bliver 70-80% fuld.

37 Kvadratisk prøvning (reducerer risikoen for klyngedannelse) Prøvningssekvens: Lineær prøvning: pos, pos + 1, pos + 2, pos + 3,... Kvadratisk prøvning:pos, pos + 1 2, pos + 2 2, pos + 3 2,... Lad H i betegne den i’te position (H 0 er startpositionen). Idet H i-1 = pos + (i - 1) 2 = pos + i 2 - 2i + 1 = H i - 2i + 1 fås H i = H i-1 + 2i - 1 Kvadrering kan undgås:

38 Implementering af kvadratisk prøvning class QuadraticProbingTable extends ProbingHashTable { protected int findPos(Object key) { int pos = key.hashCode() % array.length; int i = 0; while (array[pos] != null && !array[pos].element.equals(key)) pos = (pos + 2 * ++i - 1) % array.length; return pos; } Det kan bevises, at Hvis fyldningsgraden er mindre end 0.5, er indsættelse altid mulig, og under indsættelsen vil ingen indgang blive prøvet mere end én gang.

39 Dobbelt hashing Undgå klyngedannelse ved at bruge en ekstra hashfunktion. I stedet for som i lineær prøvning at prøve successive indgange, foretages prøvningen med en fast afstand bestemt af den anden hashfunktion. Derved øges sandsynligheden for at finde tomme indgange ved indsættelse.

40 Implementering af dobbelt hashing class DoubleHashTable extends ProbingHashTable { protected int findPos(Object key) { int pos = Math.abs(key.hashCode()) % array.length; while (array[pos] != null && !array[pos].element.equals(key)) pos = (pos + key.hash2()) % array.length; return pos; }

41 Krav til den anden hashfunktion Den bør ikke returne 0. Den skal altid returnere værdier, der er primiske med M. Kan opnås ved at vælge M som et primtal og lade h 2 (k) < M for ethvert k. Den skal være forskellig fra den første. En simpel og hurtig metode er h 2 (k) = 8 - k % 8(k % 8 er de sidste 3 bit af k)

42 Effektivitet af dobbelt hashing Dobbelt hashing bruger gennemsnitligt færre forsøg end lineær prøvning. Færre end 5 forsøg ved en søgning, når tabellen højst er 80% fuld, og færre end 5 forsøg ved en succesfuld søgning, når tabellen højst er 99% fuld. De præcise udtryk er: forsøg ved mislykket søgning, og forsøg ved succesfuld søgning, hvor  er fyldningsgraden.

43 Dobbelt hashing contra lineær prøvning   Mislykket søgningSuccesfuld søgning dobbelt hashing Mislykket søgning Succesfuld søgning   lineær prøvning

44 Fordele ved separat kædning Idiotsikker metode (bryder ikke sammen) Antallet af poster behøver ikke at være kendt på forhånd Sletning er simpel Tillader ens nøgler

45 Hashing i Java class HashMap public class HashMap { public HashMap(int initialCapacity, float loadFactor); public HashMap(int initialCapacity); public HashMap() { this(101, 0.75); } public Object put(Object key, Object value); public Object get(Object key); public Object remove(Object key); public int size(); public boolean isEmpty(); public boolean containsKey(Object key); public boolean contains(Object value); public void clear(); public Set keySet(); public Collection values(); public Set EntrySet(); }

46 Metoden get (benytter separat kædning) class Entry { Object key; Object value; Entry next; int hash; } private Entry[] table; private int count; private int threshold; private float loadFactor; public Object get(Object key) { int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % table.length; for (Entry e = table[index]; e != null; e = e.next) if (e.hash == hash && e.key.equals(key)) return e.value; return null; }

47 Metoden put public Object put(Object key, Object value) { int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % table.length; for (Entry e = tab[index]; e != null; e = e.next) if (e.hash == hash && e.key.equals(key)) { Object old = e.value; e.value = value; return old; } if (count >= threshold) { rehash(); return put(key, value); } Entry e = new Entry(); e.hash = hash; e.key = key; e.value = value; e.next = table[index]; table[index] = e; count++; return null; }

48 Metoden rehash protected void rehash() { int oldCapacity = table.length; Entry[] oldTable = table; int newCapacity = oldCapacity * 2 + 1; Entry newTable[] = new Entry[newCapacity]; threshold = (int) (newCapacity * loadFactor); table = newTable; for (int i = oldCapacity; i-- > 0; ) { for (Entry old = oldTable[i]; old != null; ) { HashtableEntry e = old; old = old.next; int index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = newTable[index]; newTable[index] = e; } }

49 Metoden remove public Object remove(Object key) { int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % table.length; for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && e.key.equals(key)) { if (prev != null) prev.next = e.next; else table[index] = e.next; count--; return e.value;} } return null; }

50 Grunde til ikke at bruge hashing Hvorfor bruge andre metoder? Der er ingen effektivitetsgaranti Hvis nøglerne er lange, kan hashfunktionen være for kostbar at beregne Bruger ekstra plads Understøtter ikke sortering

51 Prioritetskøer

52 Prioritetskøer En prioritetskø er en abstrakt datatype, der repræsenterer en endelig mængde af dataelementer forsynet med numeriske nøgler (prioriteter). Til typen er knyttet følgende 2 operationer: insert(x) : tilføj dataelementet x til mængden deleteMin : find og fjern dataelementet med den laveste prioritet En stak og en kø er specialtilfælde af en prioritetskø.

53 Anvendelser af prioritetskøer operativsystemer grafsøgning datakomprimering diskret simulering sortering

54 Specifikation i Java Undertiden er det hensigtsmæssigt med yderligere operationer, f.eks.: boolean isEmpty() : afgør om prioritetskøen er tom void join(PriorityQueue pq) : forener prioritetskøen med en anden prioritetskø ( pq ). public interface PriorityQueue { void insert(Comparable x); Comparable deleteMin(); }

55 Implementering ved hjælp af et uordnet array class ArrayPriorityQueue implements PriorityQueue { private Comparable[] array; private int currentSize; ArrayPriorityQueue() { array = new Comparable[DEFAULT_CAPACITY]; } void insert(Comparable x) { checkSize(); array[currentSize++] = x; } Comparable deleteMin() { if (currentSize == 0) throw new UnderflowException(); int min = 0; for (int i = 1; i < currentSize; i++) if (array[i].compareTo(array[min]) < 0) min = i; swapReferences(array, min, currentSize - 1); return array[--currentSize]; }

56 Implementering ved hjælp af et ordnet array Arrayet holdes sorteret i faldende orden Andre elementære implementationer: uordnede lister, ordnede lister void insert(Comparable x) { checkSize(); int i = currentSize; while (i > 0 && array[i - 1].compareTo(x) < 0)) { a[i] = a[i - 1]; i--; } array[i] = x; currentSize++; } Comparable deleteMin() { if (currentSize == 0) throw new UnderflowException(); return array[currentSize--]; }

57 Sortering af arrayet a i stigende orden: Sortering ved hjælp af prioritetskø Hvis prioritetskøen er implementeret som et uordnet array, svarer algoritmen til sortering ved udvælgelse. Hvis prioritetskøen er implementeret som et ordnet array, svarer algoritmen til sortering ved indsættelse. PriorityQueue pq = new TypePriorityQueue(); for (int i = 0; i < a.length; i++) pq.insert(a[i]); for (int i = 0; i < a.length; i++) a[i] = pq.deleteMin();

58 Implementering ved hjælp af et binært søgetræ void insert(Comparable x) { searchTree.insert(x); } Comparable deleteMin() { return searchTree.removeMin(); } Hvis søgetræet holdes balanceret, er køretiden for begge operationer O(logN). Imidlertid er implementering vanskelig (specielt removeMin ).

59 Binær hob Komplet træ: Heraf kan udledes: Den mindste nøgle findes i roden. (1)alle niveauer, eventuelt med undtagelse af det nederste, er fyldt ud med knuder; (2) knuderne på det nederste niveau er placeret helt til venstre En binær hob er et komplet binært træ (strukturbetingelse), hvor nøglen i enhver knude er mindre end eller lig med sine børns nøgler (ordningsbetingelse).

60 Eksempel på hob En hob kan repræsenteres i et array (ikke behov for hægter): roden: array[1] sønner af roden: array[2] og array[3] sønner af i : array[2*i] og array[2*i+1] far til i : array[i/2] i: array: (level order, implicit repræsentation)

61 Indsættelse af element i hob Indsæt elementet som det sidste Indsættelse af Oprethold ordningsbetingelsen ved fortsat at ombytte med faderen, så længe det er nødvendigt.

62 Implementering af insert i Java void insert(Comparable x) { checkSize(); array[++currentSize] = x; percolateUp(currentSize); } void percolateUp(int hole) { Comparable x = array[hole]; array[0] = x; for ( ; x.compareTo(array[hole] / 2) < 0; hole /= 2) array[hole] = array[hole / 2]; array[hole] = x; } percolate: sive igennem

63 Fjernelse af roden i en hob Erstat roden med det sidste element Sletning af Opret ordningsbetingelsen ved fortsat at ombytte med den mindste af sønnerne, så længe det er nødvendigt.

64 Implementering af remove i Java Comparable deleteMin() { if (isEmpty()) throw new UnderflowException(); Comparable minItem = array[1]; array[1] = array[currentSize--]; percolateDown(1); return minItem; }

65 void percolateDown(int hole) { int child; Comparable tmp = array[hole]; for ( ; hole * 2 <= currentSize; hole = child) { child = hole * 2; if (child != currentSize && array[child + 1].compareTo(array[child]) < 0) child++; if (array[child].compareTo(tmp) < 0) array[hole] = array[child]; else break; } array[hole] = tmp; } child ? hole

66 Konstruktion af hob Problem: Givet et array array [1:N] elementer i vilkårlig orden. Omordn arrayet, således at det udgør en hob. Top-til-bund-konstruktion: Induktionshypotese: array [1:i] er en hob.

67 Kompleksitet: O(  i=2..N  log(i)) = O(N log N) for (int i = 2; i <= N ; i++) percolateUp(i);

68 Bund-til-top-konstruktion: Induktionshypotese: Alle træer repræsenteret i array [i+1:N] tilfredsstiller hob- betingelserne. for (int i = N / 2; i >= 1; i--) percolateDown(i); Kompleksitet: O(  i=1..N/2  log(N/i)) = O(N) array [N/2+1:N] tilfredsstiller hob-betingelserne (de er blade i træet).

69 Heapsort (der benyttes en max-heap) Kompleksiteten af heapsort er O(N logN). Ingen brug for ekstra plads. void heapsort(Comparable[] a) { for (int i = a.length / 2; i >= 1; i--) percDown(a, i, a.length); for (int i = a.length - 1; i > 0; i--) { swapReferences(a, 0, i); percDown(a, 0, i); }

70 Eksempel på sortering Dan max-hob: fortsættes

slut

72 Animering af heapsort (hob-konstruktions-fase)

73 Animering af heapsort (sorteringsfase)

74 Tid i sekunder: Metode N = heapsort mergesort quicksort shellsort Empirisk undersøgelse af heapsort

75 Ekstern sortering (sortering på eksterne lagermedier) Særlige hensyn: (1) Det er tidsmæssigt dyrt at tilgå et dataelement (2) Der er begrænsninger på tilgangen, f.eks. kan et magnetbånd kun læses sekventielt.

76 Fordel-og-flet Fordeling: Opdel filen i blokke på størrelse med det indre lager. Sorter hver af disse blokke og fordel dem på 2 eller flere bånd. Fletning: Flet de sorterede blokke til længere sorterede blokke. Fortsæt på denne måde indtil hele filen er én sorteret blok.

77 Balanceret flervejsfletning Eksempel: 3-vejsfletning af 81 poster Sorterede blokke (længden målt i antal poster) 1 9 (3)01 (27) (3)01 (27) (3)0 1 (27) (9)0 1 (81) 5 03 (9) (9)0 3 passager for at sortere 81 poster Fletningen kan foretages ved hjælp af en prioritetskø.

78 Balanceret flervejsfletning N: antal poster M: størrelse af indre lager (målt i antal poster) Benyt halvdelen af båndene som indbånd, resten til udbånd. Passage 0:fordel filen i sorterede blokke af størrelse M på bånd 1, 2,..., k Passage 1: k-flet blokkene fra bånd 1, 2,.., k til blokke af størrelse kM ud på bånd k+1, k+2,..., 2k Passage 2: k-flet blokkene fra bånd k+1, k+2,..., 2k til blokke af størrelse k 2 M ud på bånd 1, 2,..., k.... Passage p: k-flet blokkene fra indbåndene til en blok afstørrelse k p M ud på et af på udbåndene.

79 Filen er sorteret, når k p M ≥ N d.v.s. efter p = log k (N/M) passager. Eksempel: filstørrelse10 9 poster lagerstørrelse10 6 poster antal båndstationer 4 antal passager log =10 antal båndstationer20 antal passager log = 3 Filen kan sorteres på 3-10 gange den tid, det vil tage at læse eller skrive den.

80 Polyfasesortering Reducerer antallet af bånd til cirka det halve af antallet af bånd ved balanceret flervejsfletning. Princip: Benyt hele tiden k-1 indbånd og 1 udbånd. Algoritme: Foretag fletning fra de k-1 indbånd ud på udbåndet, indtil et af indbåndene bliver tomt. Det tomme bånd tilbagespoles og benyttes som nyt udbånd for fletning fra de øvrige k-1 bånd. Således fortsættes, indtil filen er sorteret.

81 Blokfordeling ved polyfasesortering Fordeling: Fordel blokkene på k-1 bånd, således at den sidste fletning gør alle indbånd tomme samtidigt. Fordelingsmønsteret kan bestemmes ved brug af generaliserede Fibonaccital bånd, 34 blokke, 7 passager F k (N) = F k (N-1) + F k (N-2) F k (N-k) F k (0 ≤ N ≤ k-2) = 0, F k (k-1) = 1

82 Afløserteknikken (engelsk: replacement selection) En teknik, der muliggør at blokkene i fordelingsfasen kan blive af længde 2M. Organiser posterne i det inde lager som en hob. Når lageret er fyldt, og der ankommer en ny post, skrives den mindste post fra hoben ud på båndet og afløses af den nye post. Der er nu 2 tilfælde: (1) Den nye post er større end eller lig med den sidst udskrevne post. Posten indsættes i hoben. (2) Den nye post er mindre end den sidst udskrevne post. Posten tilbageholdes indtil videre. En blok er udskrevet, når alle poster i det indre lager er tilbageholdt (hoben er tom). Derefter organiseres de tilbageholdte poster som en hob, og der fortsættes som hidtil.

83 Løs følgende opgaver Opgave 46: 20.5 (1 point) Opgave 47: 21.3 (2 point) Opgave 48: 21.7 (1 point) Opgave 49: (1 point, ikke-obligatorisk) Opgave 50: (1 point, ikke-obligatorisk) Afleveringsfrist: tirsdag den 11. december Ugeseddel december december