Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als...

59
Datenstrukturen und Algorithmen Vorlesung 9

Transcript of Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als...

Page 1: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Datenstrukturen und Algorithmen

Vorlesung 9

Page 2: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Hashtabelle – als Erinnerung

• Hashtabellen sind Tabellen (Arrays), wo aber die Elemente nicht von links nach rechts eingefügt werden, wie bei typischen Arrays

• Für jedes Element, das eingefügt werden muss, wird die Position mitHilfe einer Hashfunktion berechnet

• Wenn die Hashfunktion dieselbe Position für zwei Elemente generiert, dann gibt es eine Kollision und man braucht eine Strategie für Kollisionauflösung

Page 3: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Hashtabelle – als Erinnerung

• Für unabhängige Verkettung haben wir auf jede Position eine verkettete Liste:

• Ein wichtiger Wert für eine Hashtabelle ist der Belegungsfaktor, 𝛼, der als n/mberechnet wird (n – Anzahl der Elemente, m – Anzahl der Slots)

• Für unabhängige Verkettung kann 𝛼 größer als 1 sein

Page 4: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Kollisionsauflösung: coalesced/verzahnte Verkettung

Page 5: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Coalesced/Verzahnte Verkettung (coalesced chaining)

• Kollisionsbehandlung bei coalesced Verkettung: jedes Element ausder Hashtabelle wird in der Hashtabelle direkt gespeichert (ohneverkettete Listen nach außen), aber jedes Element hat einen next Feld, ähnlich wie bei verketteten Listen auf Arrays

• Sollte beim Einfügen eine Kollision auftreten, wird der Wert in eine freie Position eingetragen und die Position in die Liste, die von der ursprünglich berechneten Position ausgeht, eingehängt (als next)

• Da sich alle Elemente in der Tabelle befinden ist 𝛼 höchstens 1

Page 6: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Coalesced/Verzahnte Verkettung - Beispiel

• Sei eine Hashtabelle mit der Größe m = 19 mit coalesced Verkettung als Kollisionsbehandlung und eine Hashfunktion mit der Divisionsmethode

• Wir wollen folgende Buchstaben (ohne Leerzeichen) in die Tabelle einfügen: A SEARCHING EXAMPLE

• Für jede Buchstabe berechnet man den Hashcode als Index der Buchstabe in dem Alphabet

Buchstabe A S E R C H I N G X M P L

Hashcode 1 19 5 18 3 8 9 14 7 24 13 16 12

h(Buchstabe) 1 0 5 18 3 8 9 14 7 5 13 16 12

Page 7: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Coalesced/Verzahnte Verkettung - Beispiel

• m = 19

• 𝛼 = 0.89

• firstFree = 15

Position 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

T S A A C E E X G H I A E L M N P R

next -1 2 10 -1 6 4 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1

Page 8: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Coalesced Verkettung – Repräsentierung

• Welche Felder braucht man für die Repräsentierung?

• Für die Vereinfachung betrachten wir nur die Schlüssel

HashTable:T:TKey[]next: Integer[]m: IntegerfirstFree: Integerh: TFunction

Page 9: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Coalesced Verkettung – insertsubalgorithm insert (ht, k) is://pre: ht ist ein HashTable, k ist ein TKey//post: k wurde in ht eingefügt

pos ← ht.h(k)if ht.T[pos] = -1 then //-1 heißt leere Position

ht.T[pos] ← kht.next[pos] ← -1

elsecurrent ← poswhile ht.next[current] ≠ -1 execute

current ← ht.next[current]end-whileif ht.firstFree = ht.m then

@resize and rehashelse

//Fortsetzung auf der nächsten Folie

Page 10: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Coalesced Verkettung – insert

• Komplexität: Θ(1) im Durchschnitt, Θ(n) im schlimmsten Fall

ht.T[ht.firstFree] ← kht.next[ht.firstFree] ← - 1ht.next[current] ← ht.firstFreechangeFirstFree(ht)

end-ifend-if

end-subalgorithm

Page 11: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Coalesced Verkettung – ChangeFirstFree

• Komplexität: Θ(m)

• Wäre es besser, die leere Positionen in einer einfach verketteten Liste zu speichern?

• Wäre es besser, die leere Positionen in einer doppelt verketteten Liste zu speichern?

subalgorithm changeFirstFree(ht) is://pre: ht ist ein HashTable//post: der Wert von ht.firstFree wird die nächste freie Position sein

ht.firstFree ← ht.firstFree + 1while ht.firstFree < ht.m and ht.T[ht.firstFree] = -1 execute

ht.firstFree ← ht.firstFree + 1end-while

end-subalgorithm

Page 12: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Coalesced Verkettung

• Die Operationen remove und search werden im Seminar 6 besprochen

• Wie kann man einen Iterator für eine Hashtabelle mit coalescedVerkettung definieren? Was sollten folgende Operationen tun?

• init

• getCurrent

• next

• valid

Page 13: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Kollisionsauflösung: offene Adressierung

Page 14: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung

• Im Falle der offenen Adressierung wird jedes Element in der Hashtabelle direkt gespeichert und es gibt keine Pointers oder nextFelder zwischen den Elementen

• Um das Einfügen mithilfe offener Adressierung durchzuführen, müssen wir die Hashtabelle sukzessive überprüfen oder sondieren, bis wird einen leeren Slot finden, an dem wir den Schlüssel speichern können

Page 15: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung

• Um die Slots zu bestimmen, die sondiert werden, erweitern wir die Hashfunktion um einen zusätzlichen Eingabeparameter, über den eine Sondierungszahl (mit 0 beginnend) übergeben wird

• Die Hashfunktion wird damit zu:

h : U × {0, 1, ..., m-1} → {0, 1, ..., m-1}

• Für ein Element wird der Reihe nach folgende Sequenz sondiert

<h(k,0), h(k,1), ..., h(k,m-1)> - Sondierungssequenz

• Für jeden Schlüssel k fordert man, dass die Sondierungssequenz eine Permutation von (0, 1, ..., m – 1) ist, sodass letztendlich jede Position der Hashtabelle als Slot für einen neuen Schlüssel berücksichtigt wird

Page 16: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – lineares Sondieren

• Eine Methode die Hashfunktion zu definieren ist lineares Sondieren:

ℎ 𝑘, 𝑖 = ℎ′ 𝑘 + 𝑖 𝑚𝑜𝑑 𝑚, ∀𝑖 = 0,… ,𝑚 − 1

• wobei h’(k) eine einfache Hashfunktion ist (z.B. h’(k) = k mod m)

• die Sondierungssequenz für lineares Sondieren ist:

<h’(k), h’(k)+1,h’(k)+2, ..., m-1, 0, 1, ..., h’(k)-1>

Page 17: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – lineares Sondieren Beispiel

• Sei eine Hashtabelle mit der Größe m = 19 mit offener Adressierung mit lineares Sondieren als Kollisionsbehandlung (h‘(k) ist eine Hashfunktion mit der Divisionsmethode)

• Wir wollen folgende Buchstaben (ohne Leerzeichen) in die Tabelle einfügen: A SEARCHING EXAMPLE

• Für jede Buchstabe berechnet man den Hashcode als Index der Buchstabe in dem Alphabet

Buchstabe A S E R C H I N G X M P L

Hashcode 1 19 5 18 3 8 9 14 7 24 13 16 12

h‘(Buchstabe) 1 0 5 18 3 8 9 14 7 5 13 16 12

Page 18: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – lineares Sondieren Beispiel

• 𝛼 = 0.89

• Nachteil des linearen Sondieren:• Es gibt nur m unterschiedliche Sondierungssequenz (nachdem man den

Anfangspunkt kennt, kennt man schon die ganze Sondierungsequenz)

• Das Problem des primären Clustern – es bilden sich lange Folgen besetzter Slots, wodurch sich die Suchzeit erhöht

Position 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

T S A A C A E E G H I X E L M N P R

Page 19: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Quadratisches Sondieren

• Verwende eine Hashfunktion der Form:

𝒉 𝒌, 𝒊 = 𝒉′ 𝒌 + 𝒄𝟏 ∗ 𝒊 + 𝒄𝟐 ∗ 𝒊𝟐 𝒎𝒐𝒅𝒎,∀𝒊 = 𝟎,… ,𝒎 − 𝟏

• wobei h’(k) eine einfache Hashfunktion ist (z.B. h’(k) = k mod m) und c1 und c2 Konstante sind (c2 sollte nicht 0 sein)

• Wenn man ein vereinfachtes Beispiel betrachtet mit c1 = 0 und c2 = 1, dann ist die Sondierungssequenz:

<k, k+1, k+4, k+9, k+16, ...>

Page 20: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Quadratisches Sondieren

• Wie kann man aber die Werte für m, c1 und c2 auswählen, sodass die Sondierungssequenz eine Permutation ist?

• Falls m eine Primzahl ist, dann ist die erste Hälfte der Sondierungssequenz eindeutig, also, sobald die Hälfte der Tabelle voll ist, kann man nicht sicherstellen, dass eine leere Position gefunden wird• z.B. m = 17, c1 = 3 , c2 = 1 (ℎ 𝑘, 𝑖 = 𝑘 𝑚𝑜𝑑 17 + 3 ∗ 𝑖 + 1 ∗ 𝑖2 𝑚𝑜𝑑 17) und

k = 13, Sondierungssequenz:<13, 0, 6, 14, 7, 2, 16, 15, 16, 2, 7, 14, 6, 0, 13, 11, 11>

• z.B. m = 11, c1 = 1 , c2 = 1 und k = 27, Sondierungssequenz:<5, 7, 0, 6, 3, 2, 3, 6, 0, 7, 5>

Page 21: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Quadratisches Sondieren

• Falls m eine Potenz von 2 ist und c1 = c2 = 0.5, dann ist die Sondierungssequenz immer eine Permutation.

• Z.B. für m = 8 und k = 3:• h(3,0) = (3 % 8 + 0.5 * 0 + 0.5 * 02) % 8 = 3• h(3,1) = (3 % 8 + 0.5 * 1 + 0.5 * 12) % 8 = 4• h(3,2) = (3 % 8 + 0.5 * 2 + 0.5 * 22) % 8 = 6• h(3,3) = (3 % 8 + 0.5 * 3 + 0.5 * 32) % 8 = 1• h(3,4) = (3 % 8 + 0.5 * 4 + 0.5 * 42) % 8 = 5• h(3,5) = (3 % 8 + 0.5 * 5 + 0.5 * 52) % 8 = 2• h(3,6) = (3 % 8 + 0.5 * 6 + 0.5 * 62) % 8 = 0• h(3,7) = (3 % 8 + 0.5 * 7 + 0.5 * 72) % 8 = 7

Page 22: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Quadratisches Sondieren

• Falls m eine Primzahl der Form 4 * k + 3 ist, c1 = 0 und c2 = (-1)i (dann ist die Sondierungssequenz +0, -1, +4, -9, usw.) dann ist die Sondierungssequenz immer eine Permutation.

• Z.B. für m = 7 und k = 3:• h(3,0) = (3 % 7 + 02) % 7 = 3• h(3,1) = (3 % 7 – 12) % 7 = 2• h(3,2) = (3 % 7 + 22) % 7 = 0• h(3,3) = (3 % 7 – 32) % 7 = 1• h(3,4) = (3 % 7 + 42) % 7 = 5• h(3,5) = (3 % 7 – 52) % 7 = 6• h(3,6) = (3 % 7 + 62) % 7 = 4

Page 23: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Quadratisches Sondieren Beispiel• Sei eine Hashtabelle mit der Größe m = 16 mit offener Adressierung

mit quadratisches Sondieren als Kollisionsbehandlung (h‘(k) ist eine Hashfunktion mit der Divisionsmethode), c1 = c2 = 0.5

• Wir wollen folgende Buchstaben in die Tabelle einfügen: HASHTABLE

• Für jede Buchstabe berechnet man den Hashcode als Index der Buchstabe in dem Alphabet

Buchstabe H A S T B L E

Hashcode 8 1 19 20 2 12 5

h‘(Buchstabe) 8 1 3 4 2 12 5

Page 24: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Quadratisches Sondieren

• ℎ 𝑘, 𝑖 = 𝑘 𝑚𝑜𝑑 16 + 0.5 ∗ 𝑖 + 0.5 ∗ 𝑖2 𝑚𝑜𝑑 16

• Nachteile des quadratischen Sondieren:• Die Leistung hängt von den Werten m, c1 und c2 ab• Das Problem des sekundäres Clustern – wenn die Anfangsslots die gleichen sind, dann

sind zwei Sondierungssequenzen gleich, denn aus h(k1,0) = h(k2,0) folgt h(k1,i) = h(k2,i) • Wie beim linearen Sondieren legt die erste sondierte Position die gesamte

Sondierungssequenz fest und so werden nur m verschiedene Sondierungssequenzen verwendet

Position 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

T A A S T B E H H L

Page 25: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

• Verwendet eine Hashfunktion der Form:

𝒉 𝒌, 𝒊 = (𝒉′ 𝒌 + 𝒊 ∗ 𝒉′′ 𝒌 ) 𝒎𝒐𝒅𝒎,∀𝒊 = 𝟎,… ,𝒎 − 𝟏

• wobei h’(k) und h’’(k) einfache Hashfunktionen sind, aber h’’(k) solltenie den Wert 0 haben

• Für einen Schlüssel, k, wird die erste sondierte Position h’(k) sein; alleanderen Positionen werden mithilfe der zweiten Hashfunktion h’’(k) berechnet

Offene Adressierung – Doppeltes Hashing

Page 26: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

• Ähnlich wie bei der quadratischen Sondieren wird nicht jede Kombination vom m und h’’(k) eine Permutation als Sondierungssequenz generieren

• Um eine Permutation zu generieren, müssen m und die Werte h’’(k) teilerfremd (relatively primes) sein. Es gibt zwei Möglichkeiten das zuerreichen: • m als Potenz von 2 zu wählen und die Funktion h’’ so zu konstruieren, dass sie

immer eine ungerade Zahl erzeugt

• m als Primzahl zu wählen und die Funktion h’’ so zu konstruieren, dass sie immer eine positive ganze Zahl kleiner als m ergibt

Offene Adressierung – Doppeltes Hashing

Page 27: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

• m als Primzahl zu wählen und die Funktion h’’ so zu konstruieren, dass sie immer eine positive ganze Zahl kleiner als m ergibt

• Zum Beispiel:

h’(k) = k % m

h’’(k) = 1 + (k % (m-1))

• Für m = 11 und k = 36:

h’(k) = 3

h’’(k) = 7

• Die Sondierungssequenz ist: <3, 10, 6, 2, 9, 5, 1, 8, 4, 0, 7>

( Hashfunktion ℎ 𝑘, 𝑖 = (ℎ′ 𝑘 + 𝑖 ∗ ℎ′′ 𝑘 ) 𝑚𝑜𝑑 𝑚 )

Offene Adressierung – Doppeltes Hashing

Page 28: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Doppeltes HashingBeispiel

Sei eine Hashtabelle mit der Größe m = 13 mit offener Adressierung mit doppeltes Hashing als Kollisionsbehandlung mit h’(k) = k % m und h’’(k) = 1 + (k % (m-1))

• Wir wollen folgende Buchstaben in die Tabelle einfügen: HASHTABLE

• Für jede Buchstabe berechnet man den Hashcode als Index der Buchstabe in dem Alphabet

Buchstabe H A S T B L E

Hashcode 8 1 19 20 2 12 5

h‘(Buchstabe) 8 1 6 7 2 12 5

h’‘(Buchstabe) 9 2 8 9 3 1 6

Page 29: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Doppeltes Hashing

• Hauptvorteil des doppelten Hashings: auch wenn h(k1,0) = h(k2,0) werden die Sondierungssequenzen nicht gleich sein, falls k1 ≠k2

• Zum Beispiel:• Buchstabe A, HashCode 1: <1, 3, 5, 7, 9, 11, 0, 2, 4, 6, 8, 10, 12>• Buchstabe N, HashCode 14: <1, 4, 7, 10, 0, 3, 6, 9, 12, 2, 5, 8, 11>

• Da jedes mögliche Paar (h’(k), h’’(k)) eine andere Sondierungssequenzen liefert, werden bei der doppelten Hashing ungefähr m2 unterschiedlichePermutationen verwendet

Position 0 1 2 3 4 5 6 7 8 9 10 11 12

T A B A H E S T H L

Page 30: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

• Wir besprechen die Implementierung der Standard Wörterbuchoperationen für Kollisionsbehandlung mit offenerAdressierung

• Wir benutzen die Notation h(k, i) für eine Hashfunktion, ohneanzugeben ob diese lineares Sondieren, quadratisches Sondierenoder doppelte Hashing benutzt (die Implementierung der Operationen unterscheidet sich nicht, nur die Implementierung von h)

Offene Adressierung – Operationen

Page 31: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Repräsentierung

• Welche Felder braucht man um eine Hashtabelle mit Kollisionsbehandlung mit offener Adressierung zu speichern?

• Für die Vereinfachung betrachten wir nur die Schlüssel

HashTable:T:TKeym: Integerh: TFunction

Page 32: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – insertsubalgorithm insert (ht, e) is://pre: ht ist ein HashTable, e ist ein TKey//post: e wurde in ht eingefügt

i ← 0pos ← ht.h(e, i)while i < ht.m and ht.T[pos] ≠ -1 execute

//-1 heißt leere Positioni ← i + 1pos ← ht.h(e, i)

end-whileif i = ht.m then

@resize and rehashelse

ht.T[pos] ← eend-if

end-subalgorithm

Page 33: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – searchfunction search (ht, e) is://pre: ht ist ein HashTable, e ist ein TKey//post: überprüft ob e in ht enthalten ist

i ← 0pos ← ht.h(e, i)while i < ht.m and ht.T[pos] ≠ -1 and ht.T.[pos] ≠ e execute

//-1 means empty spacei ← i + 1pos ← ht.h(e, i)

end-whileif i < ht.m and ht.T[pos] = e execute

search ← Trueelse

search ← Falseend-if

end-function

Page 34: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – remove

• Wie kann man ein Element aus einer Hashtabelle löschen?

• Aus einer Hashtabelle mit offener Adressierung ist es nicht einfach ein Element zu löschen:• Man kann nicht einfach die Position als leer markieren – die search Funktion

wird dann die anderen Elemente nicht mehr finden

• Man kann die Elemente nicht einfach verschieben – die search Funktion wird dann die anderen Elemente nicht mehr finden

• Die Löschoperation wird meisten implementiert indem man die leere Position mit einem speziellen Wert, DELETED, markiert

• Wie ändert dieser speziellen Wert die insert und search Operationen?

Page 35: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Offene Adressierung – Performanz

• In einer Hashtabelle mit offener Adressierung mit Belegungsfaktor 𝛼 = n/m (𝛼 < 1) ist die durchschnittliche Anzahl von Sondierungen:

• Für insert und erfolglose search:1

1 −𝛼

• Für erfolgreiche search:1

𝛼∗ 𝑙𝑛

1

1−𝛼

• Falls 𝛼 eine Konstante ist, dann ist die Komplexität Θ(1)

• Im schlimmsten Fall ist die Komplexität O(n)

Page 36: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing

Page 37: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing

• Vermute, dass man alle Schlüssel von Anfang an kennt und, dass wir unabhängige Verkettung als Kollisionsbehandlung benutzen ⇒

um so mehrere Listen man bildet, um so kürzer sind die Listen (man reduziert die Anzahl der Kollisionen) ⇒wenn man eine große Anzahl von Listen hat, dann wird jede Liste ein einziges

Element enthalten (keine Kollisionen)• Wie groß sollte die Hashtabelle sein, damit man sicherstellt, dass es keine

Kollisionen gibt?• Falls M = N2, dann kann man zeigen, dass die Tabelle mit einer

Wahrscheinlichkeit von 1/2 keine Kollisionen enthält• Man fängt an eine Hashtabelle aufzubauen. Falls man eine Kollision

entdeckt, dann wählt man eine neue Hashfunktion und man fängt neu an (man braucht höchstens 2 Versuche)

Page 38: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing

• Eine Tabelle von Größe N2 ist nicht praktisch

• Lösung anstatt:• Benutze eine Hashtabelle von Größe N (primäre Hashtabelle)• Anstatt verkettete Listen für Kollisionen zu benutzen ist jedes Element der

Hashtabelle eine Hashtabelle selber (sekundäre Hashtabelle)• Die sekundäre Hashtabelle wird die Größe nj

2 haben, wobei nj die Anzahl der Elemente aus dieser Hashtabelle ist (um garantieren zu können, dass es keineKollisionen auf der zweiten Ebene gibt)

• Jede sekundäre Hashtabelle wird mit einer unterschiedlichen Hashfunktion erstellt und wird neuerstellt, falls es eine Kollision gibt

• Das heißt perfektes Hashing

• Man kann zeigen, dass die gesamte Platz, die für die sekundäre Hashtabellen gebraucht wird, höchstens 2N ist

Page 39: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing

• Perfektes Hashing benötigt mehrere Hashfunktionen, darumbenutzen wir universelles Hashing

• Sei p eine Primzahl, größer als der größte Schlüsselwert

• Die universelle Hashfunktionen Familie H kann folgendermaßendefiniert werden:

H = { Ha,b(x) = ((a * x + b) % p) % m},

wobei 1 ≤ a ≤ p-1, 0 ≤ b ≤ p-1

• a und b werden zufällig ausgewählt bei der Initialisierung der Hashfunktion

Page 40: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing – Beispiel

• Wir wollen folgende Buchstaben in die Tabelle einfügen: PERFECT HASHING EXAMPLE

• Da wir keine Kollisionen haben wollen betrachten wir nur die unterschiedlichen Buchstaben: PERFCTHASINGXML

• Da es N = 15 Elemente gibt, wählen wir m = 15

• Für jede Buchstabe berechnet man den Hashcode als Index der Buchstabe in dem Alphabet

Buchstabe P E R F C T H A S I N G X M L

Hashcode 16 5 18 6 3 20 9 1 19 9 14 7 24 13 12

Page 41: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing – Beispiel

• p muss eine Primzahl sein größer als der maximale Schlüsselwert, also p = 29

• Die Hashfunktion ist:

Ha,b(x) = ((a * x + b) % p) % m

• Wobei a = 3 und b = 2 (zufällig) und m = 15

Buchstabe P E R F C T H A S I N G X M L

Hashcode 16 5 18 6 3 20 9 1 19 9 14 7 24 13 12

h(Hashcode) 6 2 12 5 11 4 11 5 1 0 0 8 1 12 9

Page 42: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing – Beispiel

• Kollisionen: • Position 0 – I, N • Position 1 – S, X• Position 2 – E • Position 4 – T• Position 5 – F, A• Position 6 – P• Position 8 – G • Position 9 – L• Position 11 – C, H • Position 12 – R, M

Page 43: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing – Beispiel

• Für die Positionen wo es keine Kollisionen gibt, werden wir eine sekundäre Hashtabelle mit einem Element haben und mit der Hashfunktion h(x) = 0

• Für die Positionen mit zwei Elementen werden wir eine sekundäre Hashtabelle mit 4 Positionen haben und unterschiedliche Hashfunktionen, aus derselben Familie, aber mit unterschiedlichen Werte für a und b

• Zum Beispiel für die Position 0 kann man a = 4 und b= 11 haben, dann kriegt man:

h(I) = h(9) = 2h(N) = h(14) =1

Page 44: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing – Beispiel

• Nehmen wir an, dass man die Werte a = 5 und b= 2 für die sekundäre Tabelle von der Position 1 auswählt

• Dann sind die Positionen der Elemente:

h(S) = h(19) = ((5 * 19 + 2) % 29 ) % 4 = 2

h(X) = h(24) = ((5 * 24 + 2) % 29 ) % 4 = 2

• Bei perfektes Hashing darf man keine Kollisionen haben, also man wählt eine andere Hashfunktion: andere zufällige Werte für a und b. Zum Beipsiel für a = 2 und b= 13 kriegt man h(S) = 2 und h(X) = 3

Page 45: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Perfektes Hashing

• Bei perfektes Hashing muss man höchstens 2 Positionen für ein Element überprüfen (Position in der primären und in der sekundärenTabelle)

• Das heißt im schlimmsten Fall ist die Komplexität Θ(1)

• Aber um perfektes Hashing zu benutzen braucht man statische Schlüssel: nachdem die Tabelle erstellt wurde, sollten keine neue Elemente eingefügt werden

Page 46: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing

Page 47: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing

• Bei Cockoo Hashing gibt es zwei Hashtabellen derselben Größe, jeder der Hashtabellen hat mehr als die Hälfte leer und jede Hashtabelle hat seine eigene Hashfunktion

• Um jedes Element einzufügen kann man zwei Positionen berechnen: eine in der ersten Tabelle und eine in der zweiten Tabelle. Bei CuckooHashing wird sichergestellt, dass sich ein Element auf einer dieser beiden Position befindet

• Die Suche ist einfach, da man nur auf zwei Positionen suchen muss

• Das Löschen ist einfach, da man die zwei Positionen betrachten muss und die Position, wo man das Element findet, als leer bezeichnen muss

Page 48: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing

• Wenn man ein Element einfügen will, dann berechnet man seine Position in der ersten Hashtabelle. Falls diese Position leer ist, dann fügt man das Element hier ein

• Falls die Position in der ersten Hashtabelle nicht leer ist, dann ersetzt man das Element, das sich an der Position befindet und man speichert das neue Element an dieser Position

• Das Element das ersetzt wurde wird an der Position in der zweiten Hashtabelle gespeichert. Falls diese Position besetzt ist, dann ersetzt man dieses Element mit dem neuen Element und das ersetzte Element wird in der ersten Hashtabelle eingefügt

• Man wiederholt diese Schritte bis man ein Element auf einer leeren Position einfügen muss

• Falls man zurück zu einer vorigen Position kommt, dann gibt es einen Zyklus, d.h. man kann das Element nicht einfügen ⇒ resize, rehash

Page 49: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

• Nehmen wir an, dass es zwei Hashtabelle gibt mit m = 11 Positionenund mit den folgenden Hashfunktionen:• h1(k) = k % 11

• h2(k) = (k div 11) % 11

• Wir wollen folgende Elemente einfügen: 20, 50, 53, 75, 100, 67, 105, 3, 36, 39

Position 0 1 2 3 4 5 6 7 8 9 10

T

Position 0 1 2 3 4 5 6 7 8 9 10

T

Page 50: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

• Füge 20 ein:• h1(20) = 9 – leere Position, in der ersten Tabelle eingefügt

• Füge 50 ein:• h1(50) = 6 – leere Position, in der ersten Tabelle eingefügt

Position 0 1 2 3 4 5 6 7 8 9 10

T 50 20

Position 0 1 2 3 4 5 6 7 8 9 10

T

Page 51: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

• Füge 53 ein:• h1(53) = 9 – besetzte Position

• 53 wird in der ersten Tabelle eingefügt und 20 wird in der zweiten Tabelle eingefügt an der Position h2(20) = 1

Position 0 1 2 3 4 5 6 7 8 9 10

T 50 53

Position 0 1 2 3 4 5 6 7 8 9 10

T 20

Page 52: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

• Füge 75 ein:• h1(75) = 9 – besetzte Position

• 75 wird in der ersten Tabelle eingefügt und 53 wird in der zweiten Tabelle eingefügt an der Position h2(53) = 4

Position 0 1 2 3 4 5 6 7 8 9 10

T 50 75

Position 0 1 2 3 4 5 6 7 8 9 10

T 20 53

Page 53: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

• Füge 100 ein:• h1(100) = 1 – leere Position

• Füge 67 ein:• h1(67) = 1 – besetzt

• 67 wird in der ersten Tabelle eingefügt und 100 wird in der zweiten Tabelle eingefügt an der Position h2(100) = 9

Position 0 1 2 3 4 5 6 7 8 9 10

T 67 50 75

Position 0 1 2 3 4 5 6 7 8 9 10

T 20 53 100

Page 54: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

• Füge 105 ein:• h1(105) = 6 –besetzt

• 105 wird in der ersten Tabelle eingefügt und 50 wird in der zweiten Tabelle eingefügt an der Position h2(50) = 4 – besetzt

• 50 wird in der zweiten Tabelle eingefügt und 53 wird in der ersten Tabelle eingefügt an der Position h1(53) = 9 – besetzt

• 53 wird in der ersten Tabelle eingefügt und 75 wird in der zweiten Tabelle eingefügt an der Position h2(75) = 6

Position 0 1 2 3 4 5 6 7 8 9 10

T 67 105 53

Position 0 1 2 3 4 5 6 7 8 9 10

T 20 50 75 100

Page 55: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

• Füge 3 ein:• h1(3) = 3 – leere Position

• Füge 36 ein • h1(36) = 3 – besetzt

• 36 wird in der ersten Tabelle eingefügt und 3 wird in der zweiten Tabelle eingefügt an der Position h2(3) = 0

Position 0 1 2 3 4 5 6 7 8 9 10

T 67 36 105 53

Position 0 1 2 3 4 5 6 7 8 9 10

T 3 20 50 75 100

Page 56: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

• Füge 39 ein:• h1(39) = 6 – besetzt• 39 wird in der ersten Tabelle eingefügt und 105 wird in der zweiten Tabelle eingefügt an

der Position h2(105) = 9 – besetzt • 105 wird in der zweiten Tabelle eingefügt und 100 wird in der ersten Tabelle eingefügt

an der Position h1(100) = 1 – besetzt• 100 wird in der ersten Tabelle eingefügt und 67 wird in der zweiten Tabelle eingefügt an

der Position h2(67) = 6• 67 wird in der zweiten Tabelle eingefügt und 75 wird in der ersten Tabelle eingefügt an

der Position h1(75) = 9 – besetzt• 75 wird in der ersten Tabelle eingefügt und 53 wird in der zweiten Tabelle eingefügt an

der Position h2(53) = 4• 53 wird in der zweiten Tabelle eingefügt und 50 wird in der ersten Tabelle eingefügt an

der Position h1(50) = 6 – besetzt• 50 wird in der ersten Tabelle eingefügt und 39 wird in der zweiten Tabelle eingefügt an

der Position h2(39) = 3

Page 57: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing – Beispiel

Position 0 1 2 3 4 5 6 7 8 9 10

T 100 36 50 75

Position 0 1 2 3 4 5 6 7 8 9 10

T 3 20 39 53 67 105

Page 58: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing

• Es kann sein, dass man ein Element nicht einfügen kann, falls es eine Endlosschleife gibt. In diesem Fall muss man die Größe der zwei Hashtabellen vergrößern und dann werden zufällig zwei neue Hashfunktionen gewählt und alle Elemente gerehasht

• Obwohl in manchen Fälle die Einfügeoperation viele Elemente verschiebt, kann man zeigen, falls der Belegungsfaktor kleiner als 0.5 ist, dass die Wahrscheinlichkeit einer Endlosschleife klein ist und dasses unwahrscheinlich ist, dass mehr als O(log2n) Elemente verschobenwerden

Page 59: Datenstrukturen und Algorithmen - cs.ubbcluj.rodianat/SDA/curs/V9.pdf · Hashtabelle –als Erinnerung •Für unabhängige Verkettung haben wir auf jede Position eine verkettete

Cuckoo Hashing

• Wenn man zwei Hashtabelle benutzt und jede Position aus der Hashtabelle enthällt höschstens ein Element, dann müssen die Tabellen ein Belegungsfaktor kleiner als 0.5 haben, damit es gut funktioniert

• Wenn man drei Tabellen benutzt, dann können diese den Belegungsfaktor 0.91 haben

• Wenn man vier Tabellen benutzt, dann können diese den Belegungsfaktor 0.97 haben