Hashverfahren

Werbung
Informatik I
5. Kapitel
Hashverfahren
Rainer Schrader
Zentrum für Angewandte Informatik Köln
3. Juni 2008
1 / 86
2 / 86
Hashverfahren
Hashverfahren
Gliederung
• zur Suche haben wir bisher lediglich Vergleichsoperationen auf den
• Adressberechnung durch Hashing
Schlüsseln zugelassen
• wir werden jetzt arithmetische Operationen auf den Schlüsseln
• Hashfunktionen
erlauben,
• Kollisionsbehandlung
• um daraus die mögliche Position des Datums zu berechnen.
• Anwendung von Hashfunktionen
3 / 86
4 / 86
Hashverfahren
Hashverfahren
Anwendungen:
Szenario:
Symboltabellen für Compiler
• wir müssen eine Menge von Schlüssen verwalten
• Bezeichner dürfen 80 Zeichen lang sein
• das erste Zeichen muss ein Buchstabe sein
• auf der Schlüsselmenge müssen die Operationen Einfügen,
Suchen und Löschen unterstützt werden
• die folgenden Zeichen können auch Sonderzeichen sein
• die Schlüssel entstammen einer (im allgemeinen sehr großen) Menge
• zulässige Bezeichner: 26 · 3779
• davon kommen in einem Programm nur k 26 · 3779 vor
von potentiellen Schlüsseln
5 / 86
6 / 86
Hashverfahren
Hashverfahren
gesucht: Datenstruktur,
• die Suchen, Einfügen, Entfernen effizient unterstützt
Zugangskontrolle über Personalausweise
• Personalausweise tragen eine 10-stellige Identifikationsnummer
10
• dies ergibt 10
• die Größe soll nur von der Anzahl der verwendeten Schlüssel abhängen
potentielle Nummern
• „effizient” soll bedeuten: möglichst konstante Zeit pro Operation
• für den Zugang (z.B. zu einem Industriebtrieb) kommen davon nur sehr
• wir könnten dazu verwenden
wenige in Frage
• ein Array in der Größe der Anzahl der potentiellen Schlüssel
; Platzverschwendung
analog bei der Verwaltung von Passwörtern
• eine ungeordnete verkettete Liste
; schlechte Laufzeit
7 / 86
8 / 86
Hashverfahren
Hashverfahren
Idee: „verallgemeinerte Felder“
• wir verwenden ein Feld T (m) (Hashtabelle)
• m ist die Größe der Hashtabelle
• dem Schlüssel k wird eine Adresse h(k ) in T zugeordnet
• aber zwei Schlüssel können auf dieselbe Adresse abgebildet werden
• im letzten Kapitel:
• lineare geordnete Listen
• Suchen mittels Schlüsselvergleichen
; immer noch zu aufwendig
(Kollisionen)
• jetzt:
Kollisionen:
• Adressen werden durch eine arithmetische Berechnung ermittelt
• müssen behandelt werden,
• sollen möglichst selten auftreten,
• jeder Schlüssel k wird über eine Adresse h(k ) angesprochen
• sollen möglichst effizient aufgelöst werden.
9 / 86
10 / 86
Hashverfahren
Hashverfahren
Der einfachste Fall: direkte Adressierung
• alle Schlüssel sind verschieden.
• U = {0, 1, . . . , m − 1}.
Szenario
• die Schlüssel entstammen einer (im allgemeinen großen) Menge
U (Universum)
Implementierung der Operationen:
• die zu speichernden Schlüssel K bilden eine Teilmenge von U
• üblicherweise ist |K | |U |
• verwende Feld T [0, . . . , m − 1] (Adresstabelle)
• T (k ) zeigt auf einen Datensatz mit Schlüssel k
• die Größe m der Hashtabelle wird vorab festgelegt,
• (oft ist m ≤ |K |)
• suche(T,k): gib T (k ) zurück
• ebenso die Hashfunktion h : U → {0, . . . m − 1}
• füge_ein(T,x): T (key (x )) zeigt auf x
• lösche(T,x): T (key (x )) = nil
• alle diese Operationen benötigen im worst-case O(1) Zeit.
11 / 86
12 / 86
Hashverfahren
Hashverfahren
Illustration: (m = 10)
0
10
U
(alle möglichen Schlüssel)
6
1
10
2
3
K
(aktulle Schlüssel)
10
2
5
8
5
8
3
0
9
3
• Θ(|K |) Speicherplatz
4
• Suche im Durchschnitt in Θ(1) Zeit
5
• Methode: Benutzung einer Hashfunktion
7
h : U → {0, 1, 2, . . . , m − 1}
8
9
10
7
• Ziele:
2
6
10
10
• im Allgemeinen gilt jedoch: |K | |U |
1
4
14 / 86
13 / 86
Hashverfahren
Hashtabellen
Illustration:
0
U
1
Probleme:
h(k1 )
(1) Wie soll man die Hashfunktion wählen?
h(k4 )
K
k3
k1
(2) Wie geht man mit Kollisionen um?
h(k2 ) = h(k5 )
k4
h(k3 )
k2
k5
m−1
15 / 86
16 / 86
Hashverfahren
Hashverfahren
• was zeichnet eine gute Hashfunktion aus?
Gliederung
Ziel:
• Adressberechnung durch Hashing
Die Hashadressen sollen gleichverteilt in {0, 1, . . . , m − 1} sein.
• Hashfunktionen
• die Verteilung der Adressen hängt ab von der Verteilung der Schlüssel.
• sei p(k ) die Wahrscheinlichkeit, dass Schlüssel k ∈ U vorkommt.
• Kollisionsbehandlung
• Anwendung von Hashfunktionen
Gleichverteilungsziel:
X
p(k ) =
k : h(k )=j
1
m
für j = 0, 1, . . . , m − 1.
17 / 86
18 / 86
Hashverfahren
Hashverfahren
• Generalannahme: die Schlüssel sind nichtnegative ganze Zahlen
Beispiel:
• Schlüssel sind reelle Zahlen, unabhängig gleichverteilt im Intervall [0, 1)
• dann erfüllt
• es ist immer möglich, Schlüssel so zu interpretieren, z.B.
• Charakterstrings: jedem Zeichen entspricht im ASCII-Code eine
Zahl im Bereich [0, . . . , 127]
• interpretiere String als Zahl zur Basis 128, z.B.
h(k ) = bkmc
das Gleichverteilungsziel
• p =
ˆ 112
• Problem: im Allgemeinen kennen wir p(k ) nicht.
• t =
ˆ 116
• ⇒ pt =
ˆ 112 × 128 + 116 = 14452
19 / 86
20 / 86
Hashverfahren
Hashverfahren
Divisionsmethode
Gliederung
h(k ) = k mod m
• Adressberechnung durch Hashing
Eigenschaften
• Hashfunktionen
(1) h(k ) kann schnell berechnet werden,
(2) die richtige Wahl von m (Tabellengröße) ist sehr wichtig:
• Divisionsmethode
• Multiplikationsmethode
Beispiele
• universelles Hashing
• ist m gerade, dann gilt: h(k ) gerade ⇐⇒ k gerade
• Kollisionsbehandlung
• kann z.B. dann ungünstig sein, wenn:
• Anwendung von Hashfunktionen
• die Parität von k das Geschlecht kodiert
• und K sehr viele „weibliche” Schlüssel enthält
22 / 86
21 / 86
Hashverfahren
Hashverfahren
zu (2): Man sollte vermeiden:
• Potenzen der Basis des Zahlensystems, in dem die Schlüssel
dargestellt sind:
allgemein gilt:
• m = 2i : alle bis auf die letzten i Binärziffern werden ignoriert
• m = 10i : analog bei Dezimalzahlen
• sei A ein Alphabet mit den Buchstaben 0, . . . , 2p − 1
• sei k eine Zeichenkette über A, k 0 eine Permutation von k
• dann ist: k ≡ k 0 mod 2p .
• r i : analog bei r -adischen Zahlen
• allgemeiner sollte man vermeiden: m = r i ± j für kleines j :
Übungsaufgabe: warum?
• z.B. m = 27 − 1 = 127:
• pt = (112 · 128 + 116) mod 127 = 14452 mod 127 = 101
• tp = (116 · 128 + 112) mod 127 = 14960 mod 127 = 101
• dasselbe passiert, wenn in einer längeren Zeichenkette zwei
Buchstaben vertauscht werden
23 / 86
24 / 86
Hashverfahren
Hashverfahren
Gliederung
• Gute Wahl: Primzahl m, die kein r i ± j , j klein, teilt
• Adressberechnung durch Hashing
• praktisch bewährt
• Hashfunktionen
• Divisionsmethode
• Multiplikationsmethode
Beispiel:
• die Hashtabelle soll ca. 1000 Einträge aufnehmen,
• universelles Hashing
• die Schlüssel sind Zeichenketten, interpretiert als 2-adische Zahlen
• Kollisionsbehandlung
• gute Wahl: m = 701, da 29 = 512 und 210 = 1024.
• Anwendung von Hashfunktionen
25 / 86
26 / 86
Hashverfahren
Hashverfahren
zu (2): Irrationale Zahlen sind eine gute Wahl.
Multiplikationsmethode
• zur Erinnerung:
Sei 0 < A < 1. Setze:
√
1+ 5
Φ=
= 1.6180339887 . . .
2
h(k ) = bm(k · A mod 1)c = bm (k · A − bk · Ac)c
|
{z
}
∈[0,1)
√
1− 5
Φ̂ =
= −0.6180339887 . . .
2
• beste Wahl für A nach Knuth [1973]:
Eigenschaften
A = Φ−1 =
(1) die Wahl von m ist unkritisch
2
√ = −Φ̂ =
1+ 5
√
5−1
= 0.6180339887 . . .
2
• Φ−1 ist bekannt als der goldene Schnitt
• (manchmal wird auch Φ als der goldene Schnitt bezeichnet).
(2) wir erhalten eine gleichmäßige Verteilung für U = {1, 2, . . . , n} bei
einer guten Wahl von A
27 / 86
28 / 86
Hashverfahren
Hashverfahren
goldener Schnitt:
goldener Schnitt:
• 2 Strecken der Längen a und b mit a ≥ b stehen im Verhältnis des
• goldenes Rechteck: Rechteck mit Seitenlängen im goldenen Schnitt
goldenen Schnitts, wenn gilt:
a
a+b
=
.
b
a
• Φ=
a
b
=
a+b
a
=1+
b
a
=1+
a−b
b
Schnitts teilt: Ψ = 360° − 360°
= 137, 5 . . . °
Φ
• Fibonacci-Zahlen:
1
Φ
• daraus ergibt sich das Verhältnis Φ =
• auch gilt:
• goldener Winkel Ψ: Winkel, der 360° im Verhältnis des goldenen
√
1+ 5
2
•
= 1.6180339887
Fn+1
Fn
Fn+1
Fn
=
Fn +Fn−1
Fn
=1+
Fn−1
Fn
konvergiert gegen Φ.
= Φ (stetige Teilung)
29 / 86
30 / 86
Hashverfahren
Hashverfahren
zu (2):
• irrationale Zahlen sind eine gute Wahl
• die Schlüssel 1, 2, . . . werden ziemlich gleichmäßig verteilt:
Veranschaulichung:
j `
´k
h(k ) = m k Φ−1 − bk Φ−1 c
Satz
für m = 10 und k = 1, . . . , 10.
Sei ξ eine irrationale Zahl. Plaziere in das Intervall [0, 1] die Punkte
ξ − bξc, 2ξ − b2ξc, . . . , nξ − bnξc.
h(1)
6
(i) Die entstehenden n + 1 Teilintervalle von [0, 1] haben höchstens drei
verschiedene Längen.
h(2)
2
h(3)
8
h(4)
4
h(5)
0
h(6)
7
h(7)
3
h(8)
9
h(9)
5
h(10)
1
• es treten jeweils höchstens 3 Intervalllängen auf
• die jeweils nächste Zahl fällt in ein längstes Intervall
(ii) Der nächste Punkt
(n + 1)ξ − b(n + 1)ξc
fällt in eines der größten Intervalle.
31 / 86
32 / 86
Hashverfahren
Hashverfahren
zu (1): Eine gute Wahl ist m = 2i . Dann kann h(k ) effizient berechnet
werden:
w Bits
Beispiel: (Dezimalrechnung) k = 123456, m = 10000, A = Φ−1
k
bA · 2w c
h(k ) = b10000 · (123456 · 0.61803 . . . mod 1)c
= b10000 · (76300.0041151 . . . mod 1)c
r1
= b10000 · 0.0041151 . . .c
r0
= b41.151 . . .c
h(k)
= 41
i Bits
• sei w die Wortlänge
• dann ist A = s/2w , wobei 0 < s < 2w
• k wird mit der w -bit-Zahl s = A · 2w multipliziert
• Ergebnis: 2w -bit-Zahl: r1 · 2w + r0
• Hashwert: die oberen i bits von r0 .
33 / 86
34 / 86
Hashverfahren
Hashverfahren
Beispiel: i = 5, w = 8, A = 0.101, k = 101111
Beispiel: i = 5, w = 8, A = 0.101, k = 101111
k * A = 101111 * 0.101
————–
101.111
10111.1
————–
11101.011
- 11101
————–
0.011 * 2ˆ5 = 1100 = h(k )
00101111
* 10100000
—————————————–
10111100000
1011110000000
—————————————–
1110101100000
h(k )
35 / 86
1
Überlauf
ignorieren
36 / 86
Hashverfahren
Hashverfahren
• empirisch schneidet die Multiplikationsmethode gut ab
Gliederung
• Adressberechnung durch Hashing
• trotzdem kann jede fest gewählte Hashfunktion „hereingelegt” werden:
• Hashfunktionen
• gib eine Folge von Schlüsseln ki an, die alle auf denselben Wert
abgebildet werden, d.h.
• Divisionsmethode
• Multiplikationsmethode
h(ki ) = j für festes j ∈ {0, 1, . . . , m − 1}
• universelles Hashing
• Kollisionsbehandlung
• Abhilfe: zufällige Auswahl der Hashfunktion aus einer endlichen
• Anwendung von Hashfunktionen
Menge H von möglichen Hashfunktionen.
37 / 86
38 / 86
Hashverfahren
Hashverfahren
Sei H eine Familie von Hash-Funktionen.
Schräges Beispiel
• für x ∈ U wähle h(u) in {0, 1, . . . , m − 1}
• wähle dabei zufällig, gleichverteilt und unabhängig von anderen y ∈ U
• dann ist die Wahrscheinlichkeit einer Kollision m1 :
H heißt universell, wenn für je zwei verschiedene Schlüssel x , y ∈ U gilt:
|{h ∈ H | h(x ) = h(y )}|
1
≤ .
|H|
m
• denn alle m 2 Paare
anschaulich:
• und m davon führen zu einer Kollision
• nur der m-te Teil von H führt zu einer Kollision von x und y .
• die Wahrscheinlichkeit, dass x und y bei zufälliger Wahl von h ∈ H
kollidieren, ist höchstens
“
”
h(x ), h(y ) treten gleichwahrscheinlich auf
• aber: wir hätten keine Chance, die Daten wiederzufinden
1
.
m
39 / 86
40 / 86
Hashverfahren
Hashverfahren
Wir definieren eine Funktion, die Kollisionen anzeigt:
• δ(x , y , h) =

• wir wählen h ∈ H zufällig
1
0
falls h(x ) = h(y ) und x 6= y
sonst
• mittels h bilden wir eine Folge von Schlüsseln nacheinander auf die
y ∈Y
δ(x , y , h) für Y ⊆ U
• wenn x eingefügt wird, sei eine Menge S von Schlüsseln bereits
• δ(x , Y , h) =
P
• δ(x , y , H) =
P
h∈H
Hashadressen 0, 1, . . . , m − 1 ab
eingefügt
δ(x , y , h)
• wir bewerten den Aufwand zum Einfügen von x über die Anzahl der
• d.h., H ist universell, wenn für je zwei beliebige x , y ∈ U mit
Elemente von S, mit denen x kollidiert (Begründung folgt später)
x 6= y gilt:
δ(x , y , H) ≤
|H|
m
• der zu erwartende Aufwand zum Einfügen von x ist dann E [δ(x , S, h)]
• wir schätzen E [δ(x , S, h)] ab:
42 / 86
41 / 86
Hashverfahren
E [δ(x , S, h)] =
Hashverfahren
1 X
δ(x , S, h)
|H|
E [δ(x , S, h)] =
h∈H
=
|S|
m
1 XX
δ(x , y , h)
|H|
h∈H y ∈S
Damit gilt (im Erwartungswert):
1 XX
δ(x , y , h)
=
|H|
• sei H eine universelle Klasse von Hashfunktionen,
y ∈S h∈H
=
• werde h ∈ H zufällig gewählt,
1 X
δ(x , y , H)
|H|
• sei S eine beliebige, noch so „bösartig“ gewählte Folge von Schlüsseln,
y ∈S
1 X |H|
≤
|H|
m
• dann wird S so gleichmäßig wie nur möglich in der Hashtabelle verteilt.
(H universell)
y ∈S
=
|S|
m
Bleibt, eine universelle Familie von Hashfunktionen anzugeben.
43 / 86
44 / 86
Hashverfahren
Hashverfahren
eine universelle Klasse H
Satz
ˆ
˜
H = {ha,b : ha,b (x ) = (ax + b) mod p mod m
eine universelle Klasse von Hashfunktionen.
• sei p eine Primzahl und
• U = {0, . . . , p − 1} = Zp das zugrunde liegende Universum
• sei Z∗p = {1, . . . , p − 1}
Beweis:
• sei
ˆ
˜
H = {ha,b : ha,b (x ) = (ax + b) mod p mod m
mit a ∈
Z∗p , b
Wir müssen zeigen:
|{h ∈ H | h(x ) = h(y )}|
1
≤
|H|
m
∈ Zp }.
mit a ∈ Z∗p , b ∈ Zp } ist
für alle x , y ∈ U
Äquivalent dazu ist:
|{(a, b) | ha,b (x ) = ha,b (y )}| ≤
Satz
p(p − 1)
.
m
H ist eine universelle Klasse von Hashfunktionen.
45 / 86
46 / 86
Hashverfahren
zu zeigen :
|{(a, b) | ha,b (x ) = ha,b (y )}| ≤
Hashverfahren
• Zp ist ein Körper (p prim)
• daher liefert jede Wahl von (a, b) ∈ Z∗p × Zp
• eineindeutig ein Paar u, v mit u 6= v als Lösung von
p(p − 1)
.
m
u = ax + b mod p
• seien x , y ∈ U , x 6= y
v = ay + b mod p
• sei u = ax + b mod p und v = ay + b mod p
• denn sind x , y , u, v gegebenen,
• dann lassen sich a und b bestimmen als:
• dann ist u − v = a(x − y ) mod p
• damit ist u 6= v , da a 6= 0 mod p und x − y 6= 0 mod p
• d.h. keine Kollision auf der mod p-Ebene.
a = (u − u)((x − y )−1 mod p) mod p
b = (u − ax ) mod p
47 / 86
48 / 86
Hashverfahren
Hashverfahren
Anzahl der Kollisionen = |{(a, b) | ha,b (x ) = ha,b (y )}|
Damit folgt:
= |{(u, v ) | 0 ≤ u, v ≤ p − 1, u = v mod m und u 6= v }|.
• durchläuft (a, b) den Bereich Z∗p × Zp ,
• so durchlaufen u, v den Bereich 0 ≤ u, v ≤ p − 1 und u 6= v
• somit:
Wieviele solcher Paare u, v kann es geben?
Anzahl der Kollisionen = |{(a, b) | ha,b (x ) = ha,b (y )}|
= |{(u, v ) | 0 ≤ u, v ≤ p − 1, u = v mod m und u 6= v }|.
• sei u ∈ {0, . . . , p − 1} fest
• sei v ∈ {0, . . . , p − 1} mit u 6= v und u = v mod m
• dann ist v von der Form u ± i · m mit i =
6 0
p−1
• davon kann es aber höchstens m viele geben
Damit folgt:
|{(a, b) | ha,b (x ) = ha,b (y )}| ≤
p(p − 1)
.
m
50 / 86
49 / 86
Hashverfahren
Hashverfahren
Gliederung
Daraus ergibt sich die Vorgehensweise für das Hashing:
• Adressberechnung durch Hashing
• sei die Größe von |K | in etwa bekannt
• Hashfunktionen
• wähle eine Primzahl p so dass p ≥ |K |
• Kollisionsbehandlung
• wähle zufällig und gleichverteilt a ∈ {1, . . . , p − 1}
• wähle zufällig und gleichverteilt b ∈ {0, . . . , p − 1}
• Verkettung
• offenes Hashing
• dann ist ha,b eine Hashfunktion mit geringer Kollisionszahl
• Double Hashing
• Anwendung von Hashfunktionen
51 / 86
52 / 86
Hashverfahren
Hashverfahren
U
K
Wie behandeln wir Kollisionen?
k1
k1
k4
k5
k2
k4
k5
Verkettung der Überläufer
k7
k7
k2
Jedes Element der Hashtabelle ist ein Zeiger auf eine Überlaufkette, die als
verkettete lineare Liste implementiert ist.
k3
k3
k8
k8
k6
k61
54 / 86
53 / 86
Hashverfahren
Hashverfahren
Durchführung der Operationen
Analyse für suche
• suche(T,k):
worst-case:
• beginne bei T (h(k )) und folge der Überlaufkette
• T (n) = Θ(n)
• alle Elemente werden auf denselben Platz abgebildet
• bis k gefunden oder Ende der Kette erreicht ist
• füge_ein(T,x):
average case
• suche nach k = key (x )
• ist die Suche erfolgreich: füge x nicht ein
1
• Annahmen:
• ansonsten: hänge x an das Ende seiner Überlaufkette
(1) ein gegebenes Element wird auf jeden der m Plätze mit gleicher
Wahrscheinlichkeit m1 abgebildet, unabhängig von den anderen
Elementen,
• entferne(T,x):
• suche nach k = key (x )
• ist die Suche erfolgreich: lösche x
(2) jeder der n gespeicherten Schlüssel ist mit gleicher
Wahrscheinlichkeit der gesuchte,
• ansonsten: stop
(3) die Berechnung von h(k ) benötigt konstante Zeit.
55 / 86
56 / 86
Hashverfahren
Hashverfahren
Analyse für suche
• sei der Auslastungsgrad gegeben durch
α=
n
m
T (n) =
«
n „
1X
i −1
1+
n
m
i =1
=1+
• α ist die durchschnittliche Anzahl von Elementen in einer Überlaufkette
n
1 X
(i − 1)
nm
i =1
=1+
• average case:
• erfolglose Suche: offensichtlich T (n) = α.
=1+
• erfolgreiche Suche:
=1+
• die Suche benötigt einen Schritt mehr als das vorherige
Einfügen des gesuchten Elements.
• die durchschnittliche Listenlänge beim Einfügen des i -ten
Elements ist i −1
.
m
=1+
1 n(n − 1)
·
nm
2
n−1
2m
n
1
−
2m
2m
α
1
−
2
2m
57 / 86
58 / 86
Hashverfahren
Hashverfahren
Analyse für suche
T (n) = 1 +
Gliederung
1
α
−
2
2m
• Adressberechnung durch Hashing
Bemerkung:
• Hashfunktionen
• sei die Anzahl der Plätze proportional zur Anzahl der Elemente (d.h.
n=
• Kollisionsbehandlung
O(m) bzw. α = O(1)),
• Verkettung
• offenes Hashing
• dann benötigt suche im Durchschnitt konstante Zeit.
Analyse für füge_ein:
• Double Hashing
wie für suche
• Anwendung von Hashfunktionen
Analyse für entferne: wie für suche
59 / 86
60 / 86
Hashverfahren
Hashverfahren
Sondierungsreihenfolge
Idee:
• Erweiterung der Hashfunktion auf zwei Argumente:
• anstatt neue Elemente durch Verkettung einzufügen
• benutze freie Tabellenplätze zum Speichern
h : U × {0, 1, . . . , m − 1} → {0, 1, . . . , m − 1},
• so, dass die Reihenfolge
Methode:
hh(k , 0), h(k , 1), . . . , h(k , m − 1)i
• alle Elemente werden in der Hashtabelle gespeichert
• wenn ein Platz belegt ist, so werden in einer bestimmten Reihenfolge
eine Permutation ist von h0, 1, . . . , m − 1i.
weitere Plätze ausprobiert
Annahme im weiteren: Die Hashtabelle enthält immer wenigstens einen
unbelegten Platz.
61 / 86
62 / 86
Hashverfahren
Hashverfahren
ideale Sondierungsreihenfolge: „uniformes Sondieren”
• Eigenschaften:
• jeder Schlüssel erhält mit gleicher Wahrscheinlichkeit jede der m!
• stößt man bei der Suche auf einen unbelegten Platz, so wird die
Suche als erfolglos abgebrochen
Permutationen von {0, 1, . . . , m − 1} als Sondierungsreihenfolge
zugeordnet
• wird ein Element entfernt, so könnte ein später eingefügtes
Element nicht wiedergefunden werden
• daher wird nicht wirklich entfernt, sondern nur als „entfernt”
markiert
• beim Einfügen wird dieser Platz als frei angesehen
• uniformes Sondieren verallgemeinert uniformes Hashing:
• es liefert nicht nur eine Adresse, sondern eine Sondierungsreihenfolge
• beim Suchen wird er als belegt betrachtet
• in der Praxis Annäherung durch:
• schwierig zu implementieren
• lineares Sondieren
• quadratisches Sondieren
• Nachteil: Die Suchzeit ist nicht mehr proportional zu (1 + α),
• (da der wahre Auslastungsgrad α nicht der aktuelle ist)
• deshalb: Wenn lösche benötigt wird, besser Verkettung der
• double hashing
Überläufer.
• uniformes Sondieren dient als Vergleichsstandard
63 / 86
64 / 86
Hashverfahren
Hashverfahren
Lineares Sondieren
• gegeben eine normale Hashfunktion
h 0 : U → {0, 1, . . . , m − 1}
Analyse zum uniformen Sondieren
• setze
Die durchschnittliche Anzahl von Sondierungen (ohne Beweis):
• erfolglose Suche ≈
• Einfügen ≈
h(k , i ) = (h 0 (k ) + i ) mod m für i = 0, 1, . . . , m − 1.
1
1−α
• zu Schlüssel k werden nacheinander die Adressen
1
1−α
h 0 (k ), h 0 (k ) + 1, h 0 (k ) + 2, h 0 (k ) + 3, . . .
• erfolgreiche Suche ≈
1
α
ln
1
1−α
(jeweils modulo m) getestet
Nachteil:
• die erste Position legt die gesamte Sequenz fest
• es gibt nur m verschiedene Sondierungsfolgen
• anstatt der m! bei uniformer Sondierung
66 / 86
65 / 86
Hashverfahren
Hashverfahren
Beispiel: m = 8, h 0 (k ) = k mod m
Lineares Sondieren neigt zu „primärer Häufung”:
Schlüssel
k
h 0 (k )
10
2
19
3
31
7
22
6
14
6
16
0
• lange belegte Teilstücke tendieren dazu, schneller zu wachsen als kurze
• Begründung:
0
1
2
3
4
5
14 16 10 19
6
7
• die Hashfunktion fülle jede Position mit gleicher Wahrscheinlichkeit
22 31
(uniform)
• betrachte eine freie Position x der Tabelle
Durchschnittliche Zeit für erfolgreiche Suche
k
ist
9
6
10
1
+
19
1
+
31
1
+
22
1
• die davor liegenden i Tabellenelemente seien bereits belegt
+
14
3
+
16
2
=
• dann wird x beim nächsten Einfügen mit Wahrscheinlichkeit
9
i +1
m
= 1, 5.
ebenfalls belegt
• damit wächst die Wahrscheinlichkeit mit der Länge der belegten Kette
67 / 86
68 / 86
Hashverfahren
Hashverfahren
Quadratisches Sondieren
h(k , i ) = (h 0 (k ) ± c1 i ± c2 i 2 ) mod m
Analyseergebnisse (ohne Beweis):
• sei 0 < α =
n
m
<1
Beispiel:
• Anzahl Sondierungen im Durchschnitt:
m = 8, h 0 (k ) = k mod m, c1 = c2 = 12 , gleiche Schlüssel wie vorhin
“
”
1
• bei erfolglose Suche ≈
1 + (1−α)
2
“
”
1
• bei erfolgreiche Suche ≈ 12 1 + 1−α
1
2
k
h 0 (k )
0
10
2
1
19
3
2
3
10 19
31
7
22
6
4
5
14
6
6
16
0
7
22 31
69 / 86
70 / 86
Hashverfahren
k
h 0 (k )
10
2
19
3
31
7
22
6
14
6
0
16
0
1
2
3
4
5
10 19
Hashverfahren
6
7
Bemerkungen:
22 31
• wie beim linearen Sondieren gibt es nur m verschiedene
−→
14
6 → 6+
1
(1
2
2
+ 1 ) mod 8 = 7 → 6 +
1
(2
2
Sondierungsfolgen („sekundäre Häufung“)
2
+ 2 ) mod 8 = 1
• aber: geeignete Wahl von m, c1 , c2 führt in der Praxis zu besserer
0
1
2
3
4
5
16 14 10 19
6
Verteilung
7
• die Wahl muss sicherstellen, dass ein freier Platz gefunden wird
22 31
• kann u.a. gezeigt werden für (jeweils mod m)
h 0 (k , i ) = h(k ) − (−1)i ·
Die durchschnittliche Zeit für erfolgreiche Suche
k
ist
8
6
10
1
+
19
1
+
31
1
+
22
1
+
14
3
+
16
1
=
“l i m”2
2
• ergibt die die Folge h(k ), h(k ) + 1, h(k ) − 2, h(k ) + 4, h(k ) − 4, . . .
• für Primzahlen der Form m = 4j + 3 durchläuft die Sondierung alle
8
Adressen
= 1, 33.
71 / 86
72 / 86
Hashverfahren
Hashverfahren
durchschnittliche Anzahl von Sondierungen:
• Analyseergebnisse (ohne Beweis):
“
”
1
− α + ln 1−α
”
“
1
• erfolgreiche Suche ≈ 1 + ln 1−α
− α2
• erfolglose Suche ≈
α
1
1−α
0.5
0.9
0.95
1.0
Sondierungen im Durchschnitt.
Verkettung
erfolgreich erfolglos
1.250
0.50
1.450
0.90
1.475
0.95
1.500
1.00
offene Hashverfahren
lineares S.
quadr. S.
uniform
er
el
er
el
er
el
1.5
2.5
1.44
2.19
1.39
2
5.5
50.5
2.85 11.40 2.56 10
10.5 200.5 3.52 22.05 3.15 20
——–
——–
——-
Quadratisches Sondieren ist schon sehr gut.
74 / 86
73 / 86
Hashverfahren
Hashverfahren
Double Hashing
Gliederung
• seien h1 , h2 : U → {0, 1, . . . , m − 1} zwei normale Hashfunktionen
• setze
• Adressberechnung durch Hashing
• Hashfunktionen
h(k , i ) = (h1 (k ) + i · h2 (k )) mod m.
• Kollisionsbehandlung
• Verkettung
• offenes Hashing
Die Sondierungsfolge hängt in zweifacher Weise vom Schlüssel ab:
• erste Sondierungsposition (wie gehabt)
• Schrittweite (neu)
• double Hashing
• Anwendung von Hashfunktionen
Es ergeben sich Θ(m 2 ) verschiedene Sondierungsfolgen.
75 / 86
76 / 86
Hashverfahren
Hashverfahren
Beispiel für (2): m = 7, h1 (k ) = k mod 7, h2 (k ) = 1 + (k mod 5)
Bedingung an h2 :
k
h1 (k )
h2 (k )
• für alle Schlüssel k muss h2 (k ) relativ prim zu m sein
• d.h. ggT(h2 (k ), m) = 1,, ansonsten wird die Tabelle nicht vollständig
10
3
1
19
5
5
31
3
2
22
1
3
14
0
5
16
2
2
durchsucht
• falls ggT(h2 (k ), m) = d > 1, so wird nur
1
-tel
d
0
durchsucht.
1
2
3
10
Zwei Vorschläge:
4
5
6
0
19
1
2
3
4
5
6
0
1
2
3
4
5
6
31 22
10
19
31 22 16 10
19 14
(3)
(1)
(2)
(1)
(2)
(4)
(3)
(5)
Durchschnittliche Zeit für erfolgreiche Suche
(1) m = 2p (schlecht für Divisionsmethode), h2 (k ) immer ungerade
(2) m Primzahl, 0 < h2 (k ) < m, z.B.
h1 (k ) = k mod m
k
h2 (k ) = 1 + (k mod m 0 )
mit m 0 = m − 1 oder m 0 = m − 2.
ist
12
6
10
1
+
19
1
+
31
3
+
22
1
+
14
5
+
16
1
=
12
= 2.00. (Untypisch schlechtes Beispiel für double hashing.)
Double Hashing ist eine gute Approximation an uniformes Hashing
77 / 86
78 / 86
Hashverfahren
Hashverfahren
Verbesserung von Brent
• sei k ein Schlüssel, der eingefügt werden soll
• sei j der sondierte Platz
• falls j bereits mit Schlüssel k 0 belegt ist, setze
Beobachtung:
• es werde eine Folge von Schlüsseln in die Hashtabelle eingefügt,
• dann hängt die Anzahl der erforderlichen Schritte von der Reihenfolge
j1 = j + h2 (k ) mod m
der Schlüssel ab
j2 = j + h2 (k 0 ) mod m
• ist j1 frei oder j2 belegt, so fahre fort wie im Original mit j = j1
• sonst (j1 belegt und j2 frei) setze
• ; versuche, die Reihenfolge nachträglich zu ändern
T (j2 ) = T (j )
T (j ) = k
79 / 86
80 / 86
Hashverfahren
Hashverfahren
Beispiel: m = 7, h1 (k ) = k mod 7, h2 (k ) = 1 + (k mod 5)
k
h1 (k )
h2 (k )
10
3
1
0
19
5
5
31
3
2
1
2
22
1
3
3
4
10
0
1
2
3
4
5
6
14
0
5
5
16
2
2
Analyseergebnis (ohne Beweis):
6
• erfolglose Suche ≈
19
1
1−α
(wie uniform)
• erfolgreiche Suche < 2.5 (unabhängig von α)
31
14 22 16 10 10 19
0
31
1
2
3
4
5
6
Sondierungen im Durchschnitt.
31 10 19
Rest immer frei
Durchschnittliche Zeit für erfolgreiche Suche
k
ist
7
6
10
2
+
19
1
+
31
1
+
22
1
+
14
1
+
16
1
=
7
= 1.17.
81 / 86
82 / 86
Hashverfahren
Hashverfahren
• oft sind Hashfunktionen Einwegfunktionen:
Gliederung
• Adressberechnung durch Hashing
• gegeben f und x , so ist f (x ) schnell zu berechnen
• Hashfunktionen
• gegeben f und f (x ), so ist x kaum oder nur sehr aufwendig zu
berechnen
• Kollisionsbehandlung
• diese Eigenschaft wird in der sicheren Übermittlung von Daten
• Anwendung von Hashfunktionen
ausgenutzt
83 / 86
84 / 86
Hashverfahren
Hashverfahren
• Übermittlung von offenen Dokumenten, so dass
• Empfänger
• Verfälschungen entdeckt werden können,
• wendet Hashfunktion auf Dokument x an, erzeugt so den Wert
f (x )
• entschlüsselt p(f (x )) mit öffentlichem Schlüssel o
• der Absender sich identifizieren kann
• Verwendung von privaten (geheimen) und öffentlichen Schlüsseln
• erhält somit f 0 (x ) = o(p(f (x )))
• Absender
• ist f (x ) 6= f 0 (x ), so ist
• wendet Hashfunktion auf Dokument x an,
• Unterschrift falsch, oder
• erzeugt so den Wert f (x )
• verschlüsselt f (x ) mit seinem privaten Schüssel p
• Dokument verfälscht
• sendet x und p(f (x )) als „Unterschrift”
85 / 86
86 / 86
Herunterladen