slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Hashing PowerPoint Presentation
Download Presentation
Hashing

Loading in 2 Seconds...

play fullscreen
1 / 83

Hashing - PowerPoint PPT Presentation


  • 240 Views
  • Uploaded on

Hashing. Plan. Hashing Hashfunktioner Kollisionsstrategier Effektivitet Hashing i Javas biblioteker Prioritetskøer Binær hob Anvendelser: heapsort, ekstern sortering. Hashing søgning ved nøgletransformation.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Hashing' - dalit


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide2

Plan

  • Hashing Hashfunktioner Kollisionsstrategier Effektivitet Hashing i Javas biblioteker
  • Prioritetskøer Binær hob Anvendelser: heapsort, ekstern sortering
hashing s gning ved n gletransformation
Hashingsøgning ved nøgletransformation
  • Med balancerede træer foretages O(log2N) sammenligninger af nøgler.
  • Men er O(log2N) 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).
grundl ggende ide

h: K I

Grundlæggende ide

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.

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.

tid plads afvejning trade off
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
hashingteknikken
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).
gode hashfunktioner
“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.
konstruktion af hashfunktioner korte n gler
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]
eksempel med korte n gler
Eksempel med korte nøgler
  • Nøgler bestående af 4 ascii-tegn, tabelstørrelse 101.
  • ascii ab c d
  • hex 6 16 2 6 3 6 4
  • bin 01100001011000100110001101100100

0x61626364 = 1633831724

16338831724 % 101 = 11 Nøglen "abcd" hasher til 11.

0x64636261 = 1684234849 1684234849 % 101 = 57 Nøglen "dcba" hasher til 57.

0x61626263 = 1633837667 1633837667 % 101 = 57Nøglen "abbc" hasher også til 57. Kollision!

konstruktion af hashfunktioner lange n gler
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.
eksempel med lange n gler
Eksempel med lange nøgler
  • Eksempel med 4 tegn. Men metoden virker også for vilkårligt lange nøgler.
  • Benyt Horners regel:
  • 0x61626364 =
  • 97*2563 + 98*2562 + 99*2561 + 100=
  • ((97*256 + 98)*256 + 99)*256 + 100
  • Tag modulo efter hver addition for at undgå aritmetisk overløb:
  • (97*256 + 98 = 24930) % 101 = 84
  • (84*256 + 99 = 21603) % 101 = 90
  • (90*256 + 100 = 23140) % 101 = 11
tabelst rrelsen
Tabelstørrelsen
  • Vælg tabelstørrelsen som et primtal. Hvorfor?
  • I eksemplet før havde vi "abcd" = 0x61626364 =
  • 97*2563 + 98*2562 + 99*2561 + 100
  • 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.
eksempel p hashfunktion

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;
  • }
Eksempel på hashfunktion
  • 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;
  • }

For at sprede værdierne bedre er 256 erstattet med 37.

Modulo-beregningerne undervejs kan undværes:

javas implementering af hashcode i string java 1 1
Javas implementering af hashCode i String(Java 1.1)

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;

}

slide15

Javas implementering af hashCode i String(Java 1.2)

  • publicint 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;
  • }
hyppigheden af kollisioner

Hvis M være tabelstørrelsen, hvor mange indsættelser kan da i gennemsnit foretages, før der opstår en kollision?

M

100 12

365 24

1000 40

10000 125

100000 396

1000000 2353

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.
kollisionstrategier

Mulighed 2 (åben adressering):

Sørg for at N < M:

Læg kolliderende nøgler i tabellen.

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).
separat k dning
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.

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;

...

}

Implementering af separat kædning
slide20

class HashEntry {

HashEntry(Object k, Object v, HashEntry n)

{ key = k; value = v; next = n; }

Object key, value;

HashEntry next;

}

slide21

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;

}

slide22

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;

}

}

prev

e

e.next

effektivitet af separat k dning
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
ben adressering line r pr vning
Åben adresseringLineæ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.
et simpelt eksempel

0

1

2

3

4

5

6

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) % 7
slide26

N

0

1

2

C

3

K

4

S

5

6

  • Tabel efter indsættelse af nøglerne
  • C, K, N, S

h(N) = 14 % 7 = 0

h(C) = 3 % 7 = 3

h(K) = 11 % 7 = 4

h(S) = 19 % 7 = 5

inds ttelse af y giver kollision

N

0

1

2

C

3

h(Y) = 25 % 7 = 4

K

4

S

5

6

N

0

1

2

C

3

K

4

S

5

Y

6

Placering efter 3 forsøg

Indsættelse af Y giver kollision
slide28

N

0

1

2

C

3

h(D) = 4 % 7 = 4

K

4

S

5

Y

6

N

0

D

1

2

C

3

K

4

S

5

Y

6

Placering efter 5 forsøg

(med “wrap around”)

Indsættelse af D

Bemærk: tabellen må ikke blive fuld!

slide29

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;

}

slide30

class HashEntry {

HashEntry(Object k, Object v)

{ key = k; value = v; }

Object key, value;

boolean isActive = true;

}

Object get(Object key) {

int pos = findPos(key);

if (array[pos] == null || !array[pos].isActive)

return null;

return array[pos].value;

}

void remove(Object key) {

int pos = findPos(key);

if (array[pos] == null)

return;

array[pos].isActive = false;

}

slide31

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.

slide32

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

slide33

De præcise udtryk er:

forsøg ved mislykket søgning, og

forsøg ved succesfuld søgning,

hvor  = N/M betegner fyldningsgraden.

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.
slide34

a

a

Mislykket søgning

Succesfuld søgning

Effektivitetskurver for lineær prøvning

argumentation for tendens til klyngedannelse

Antag at alle positioner [i:j] indeholder poster, mens i-1, j+1 og j+2 er tomme.

i-1

j+1

j+2

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.

klyngedannelse
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.
slide37

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 + 12, pos + 22, pos + 32, ...

Kvadrering kan undgås:

Lad Hi betegne den i’te position (H0 er startpositionen).

Idet Hi-1 = pos + (i - 1)2 = pos + i2 - 2i + 1 = Hi - 2i + 1

fås Hi = Hi-1 + 2i - 1

slide38

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;

}

}

Implementering af kvadratisk prøvning

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.

dobbelt hashing
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.

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;

}

}

Implementering af dobbelt hashing
krav til den anden hashfunktion
Krav til den andenhashfunktion
  • 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 h2(k) < M for ethvert k.
  • Den skal være forskellig fra den første.
  • En simpel og hurtig metode er h2(k) = 8 - k % 8 (k % 8 er de sidste 3 bit af k)
slide42

De præcise udtryk er:

forsøg ved mislykket søgning, og

forsøg ved succesfuld søgning,

hvor  er fyldningsgraden.

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.
slide43

dobbelt hashing

Succesfuld søgning

Mislykket søgning

lineær prøvning

a

a

Mislykket søgning

Succesfuld søgning

a

a

Dobbelt hashing contra lineær prøvning

fordele ved separat k dning
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
hashing i java class hashmap
Hashing i Javaclass 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(); }

metoden get benytter separat k dning

class Entry {

Object key;

Object value;

Entry next;

int hash;

}

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;

}

Metoden get(benytter separat kædning)

private Entry[] table;

private int count;

private int threshold;

private float loadFactor;

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;

}

Metoden put
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; }

}

}

Metoden rehash
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;

}

Metoden remove
grunde til ikke at bruge hashing
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
prioritetsk er
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ø.

anvendelser af prioritetsk er
Anvendelser af prioritetskøer
  • operativsystemer
  • grafsøgning
  • datakomprimering
  • diskret simulering
  • sortering
specifikation i java

public interface PriorityQueue {

void insert(Comparable x);

Comparable deleteMin();

}

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).

implementering ved hj lp af et uordnet array
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];
  • }
  • }
implementering ved hj lp af et ordnet array

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--];

}

Implementering ved hjælp af et ordnet array

Arrayet holdes sorteret i faldende orden

Andre elementære implementationer:

uordnede lister, ordnede lister

sortering ved hj lp af prioritetsk

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();

Sortering ved hjælp afprioritetskø
  • Sortering af arrayet ai stigende orden:

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.

slide58

void insert(Comparable x) {

searchTree.insert(x);

}

Comparable deleteMin() {

return searchTree.removeMin();

}

Implementering ved hjælp af et binært søgetræ

Hvis søgetræet holdes balanceret, er køretiden for begge operationer O(logN).

Imidlertid er implementering vanskelig (specielt removeMin).

bin r hob
Binær hob

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).

Heraf kan udledes: Den mindste nøgle findes i roden.

Komplet træ:

(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

eksempel p hob

1

13

2

3

21

16

4

5

6

7

24

19

31

68

8

9

10

65

26

32

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: 0 1 2 3 4 5 6 7 8 9 10 array:13 21 16 24 31 19 68 65 26 32

(level order, implicit repræsentation)

slide61

13

13

21

16

16

14

24

24

19

19

31

21

68

68

31

65

26

65

26

32

32

14

Indsættelse af 14

Indsættelse af element i hob

Indsæt elementet som det sidste.

Oprethold ordningsbetingelsen ved fortsat at ombytte med faderen,

så længe det er nødvendigt.

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;

}

Implementering af insert i Java

percolate: sive igennem

slide63

14

13

21

16

16

14

24

19

31

24

19

68

21

68

31

65

26

32

65

26

32

Fjernelse af roden i en hob

Erstat roden med det sidste element.

Opret ordningsbetingelsen ved fortsat at ombytte med

den mindste af sønnerne, så længe det er nødvendigt.

Sletning af 13

implementering af remove i java

Comparable deleteMin() {

if (isEmpty())

throw new UnderflowException();

Comparable minItem = array[1];

array[1] = array[currentSize--];

percolateDown(1);

return minItem;

}

Implementering af remove i Java
slide65

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;

}

hole

child ?

konstruktion af hob
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.
slide67

for (int i = 2; i <= N; i++)

percolateUp(i);

  • Kompleksitet:
  • O(i=2..Nlog(i)) = O(N log N)
slide68

for (int i = N / 2; i >= 1; i--)

percolateDown(i);

  • Bund-til-top-konstruktion: Induktionshypotese: Alle træer repræsenteret i array[i+1:N] tilfredsstiller hob-betingelserne.

array[N/2+1:N] tilfredsstiller hob-betingelserne (de er blade i træet).

Kompleksitet: O(i=1..N/2log(N/i)) = O(N)

heapsort der benyttes en max heap

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);

}

}

Heapsort(der benyttes en max-heap)
  • Kompleksiteten af heapsort er O(NlogN).
  • Ingen brug for ekstra plads.
slide70

59 26 58 21 41 97 21 16 26 53

97 53 59 26 41 58 31 16 21 36

59 53 58 26 41 36 31 16 21 97

58 53 36 26 41 21 31 16 59 97

53 41 36 26 16 21 31 5859 97

41 31 36 26 16 21 535859 97

97

53

59

26

41

58

31

16

21

36

Eksempel på sortering

Dan max-hob:

fortsættes

slide71

41

41 31 36 26 16 21 535859 97

36 31 21 26 16 41535859 97

31 26 21 16 3641535859 97

26 16 21 313641535859 97

21 16 26313641535859 97

16 21 26313641535859 97

31

21

26

16

slut

slide74

Empirisk undersøgelse af heapsort

  • Tid i sekunder:
  • Metode N = 32000 64000 128000 256000 512000 1024000
  • heapsort 0.03 0.07 0.16 0.32 0.94 2.10
  • mergesort 0.06 0.12 0.25 0.54 1.15 2.67
  • quicksort 0.03 0.05 0.09 0.17 0.36 0.76
  • shellsort 0.04 0.08 0.18 0.41 1.03 2.37
slide75

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.

slide76

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.

slide77

Sorterede blokke (længden målt i antal poster)

1 9 (3) 0 1 (27) 0

2 9 (3) 0 1 (27) 0

3 9 (3) 0 1 (27) 0

4 0 3 (9) 0 1 (81)

5 0 3 (9) 0

6 0 3 (9) 0

3 passager for at sortere 81 poster

Fletningen kan foretages ved hjælp af en prioritetskø.

Balanceret flervejsfletning

Eksempel: 3-vejsfletning af 81 poster

slide78

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 k2M ud på bånd 1, 2, ..., k.

... Passage p: k-flet blokkene fra indbåndene til en blok af størrelse kpM ud på et af på udbåndene.

slide79

Filen kan sorteres på 3-10 gange den tid, det vil tage at læse

eller skrive den.

Filen er sorteret, når

kpM ≥ N

d.v.s. efter

p = logk(N/M) passager.

Eksempel:

filstørrelse 109 poster

lagerstørrelse 106 poster

antal båndstationer 4

antal passager log2103 = 10

antal båndstationer 20

antal passager log10103 = 3

slide80

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.

slide81

1 21 8 0 5 3 1 0 1

2 130 8 3 0 2 1 0

3 0 13 5 0 2 0 1 0

3 bånd, 34 blokke, 7 passager

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.

Fk(N) = Fk (N-1) + Fk (N-2) + ... + Fk (N-k)

Fk (0 ≤ N ≤ k-2) = 0, Fk (k-1) = 1

slide82

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.

slide83

Ugeseddel 124. december - 11. december

• 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: 21.22 (1 point, ikke-obligatorisk)

Opgave 50: 21.23 (1 point, ikke-obligatorisk)

Afleveringsfrist: tirsdag den 11. december