G.Heyer Algorithmen und Datenstrukturen 1 13. Kapitel: Hashfunktionen 1) Divisionsrest-Verfahren (...

Post on 05-Apr-2015

104 views 0 download

Transcript of G.Heyer Algorithmen und Datenstrukturen 1 13. Kapitel: Hashfunktionen 1) Divisionsrest-Verfahren (...

G.Heyer Algorithmen und Datenstrukturen1

13. Kapitel: Hashfunktionen

1) Divisionsrest-Verfahren ( kurz: Divisionsverfahren)

h(Ki) = Ki mod q, (q ~ m)Der entstehende Rest ergibt die relative Adresse in HT.

Beispiel:

Die Funktion nat wandle Namen in natürliche Zahlen um:nat(Name) = ord (1. Buchstabe von Name ) - ord (“A”)h (Name) = nat (Name) mod m

G.Heyer Algorithmen und Datenstrukturen2

Hash-Tabelle:m = 10 Schlüssel Daten

0

1

2

3

4

5

6

7

8

9

BOHR D1

CURIE D2

DIRAC D3

EINSTEIN D4

PLANCK D5

HEISENBERG D7

SCHRÖDINGER D8

G.Heyer Algorithmen und Datenstrukturen3

Divisionsrest- Verfahren: Forderungen an Divisor q1) m > n• Belegungsfaktor von HT: Verhältnis von aktuell belegten

Speicherplätzen (n) zur gesamten Anzahl der

Speicherplätze (m) = na / m• Für 0.85 erzeugen alle Hash-Funktionen viele

Kollisionen und damit einen hohen Zusatzaufwand.

2) q gerade Zahl

sonst bleibt h (Ki) bei geradem Ki gerade und bei

ungeradem Ki ungerade.

3) q bk

b sei die Basis der Schlüsseldarstellung. Wenn q = bk ist,

dann liefert h (Ki) die letzten k Stellen von Ki.

h(Ki) = Ki mod q

G.Heyer Algorithmen und Datenstrukturen4

4) q a * bk ca und c seien kleine ganze Zahlen. Der Divisor q soll nicht benachbart zu einer Potenz des Zahlensystems (in dem die Division durchgeführt wird) liegen, da sonst

(x + a * bk c ) mod q ~ x mod q ist, d. h., bei

gleichen Endziffern wiederholt sich fast die gleiche Menge von Adressen in verschiedenen Zahlenbereichen.

5) q = Primzahl ( größte Primzahl <= m)

Die Hash-Funktion muss etwaige Regelmäßigkeiten in der Schlüsselverteilung eliminieren, damit nicht ständig die gleichen Plätze der HT getroffen werden.

Bei äquidistantem Abstand der Schlüssel

Ki + j * K, j = 0, 1, 2, ,... maximiert eine Primzahl die Distanz, nach der eine Kollision auftritt.

G.Heyer Algorithmen und Datenstrukturen5

Eine Kollision ergibt sich, wennKi mod q = (Ki + j * K) mod q oder

j * K = k * q, k = 1, 2, 3, ...

Eine Primzahl kann keine gemeinsamen Faktoren mit K besitzen, die den Kollisionsabstand verkürzen würden.

==> wichtigste Forderung an q !

2) Faltung

• Schlüssel wird in Teile zerlegt, die bis auf das letzte die

Länge einer Adresse für HT besitzen.

• Schlüsselteile werden dann übereinander gefaltet und

addiert.

G.Heyer Algorithmen und Datenstrukturen6

3) Mid-Square-Methode• Schlüssel Ki wird quadriert, t aufeinanderfolgende Stellen

werden aus der Mitte des Ergebnisses für die Adressierung

ausgewählt.

• Es muss also bt = m gelten.

• Mittlere Stellen lassen beste Gleichverteilung der Werte

erwarten.

• Beispiel für b = 2, t = 4, m = 16 : Ki = 1100100

Ki2 = 10011100010000 h (Ki) = 1000

t

G.Heyer Algorithmen und Datenstrukturen7

4) Weitere Verfahren

• Zufallsmethode: Ki dient als Saat für Zufallszahlengenerator

• Ziffernanalyse: setzt Kenntnis der Schlüsselmenge K voraus.

Die t Stellen mit der besten Gleichverteilung der Ziffern

oder Zeichen in K werden von Ki zur Adressierung

ausgewählt.

Bewertung

Das Verhalten einer Hash-Funktion hängt von der gewählten Schlüsselmenge ab.

Deshalb lassen sie sich auch nur unzureichend theoretisch oder mit Hilfe von analytischen Modellen untersuchen.

G.Heyer Algorithmen und Datenstrukturen8

Über die Güte der verschiedenen Hash-Funktionen liegen

jedoch eine Reihe von empirischen Untersuchungen vor.• Das Divisionsrest-Verfahren ist im Mittel am

leistungsfähigsten; für bestimmte Schlüsselmengen können

jedoch andere Techniken besser abschneiden.

• Keine Hash-Funktion ist immer besser als alle anderen.

• Wenn die Schlüsselverteilung nicht bekannt ist, dann ist

das Divisionsrest-Verfahren die bevorzugte Hash-Technik.

==> Wenn eine Hash-Funktion gegeben ist, lässt sich immer eine Schlüsselmenge finden, bei der sie besonders viele Kollisionen erzeugt.

G.Heyer Algorithmen und Datenstrukturen9

Behandlung von KollisionenZwei Ansätze, wenn h (Kq) = h (Kp):

• Es wird für Kp eine freier Platz in HT gesucht ; alle

Überläufer werden im Primärbereich untergebracht

(open adressing).

• Kp wird in einem separaten Überlaufbereich zusammen mit

allen anderen Überläufern gespeichert (separate overflow)

Die Methode der Kollisions-Auflösung entscheidet darüber, welche Folge und wie viele relative Adressen zur Ermittlung eines freien Platzes aufgesucht werden.

G.Heyer Algorithmen und Datenstrukturen10

Adressfolge bei Speicherung und Suche für Schlüssel Kp sei

h0(Kp), h1(Kp), h2(Kp), ...

• Bei einer Folge der Länge n treten also n-1 Kollisionen auf

• Primärkollision: h (K p) = h (K q)

• Sekundärkollision: h i (Kp) = h j(Kq) , i j

Offene Hash-Verfahren

Speicherung der Synonyme (Überläufer) im Primärbereich

Das eingesetzte Hash-Verfahren muss in der Lage sein, eine Sondierungsfolge, d. h. eine Permutation aller Hash-Adressen, zu berechnen.

G.Heyer Algorithmen und Datenstrukturen11

1) Lineares Sondieren (linear probing)

Von der Hausadresse aus wird sequentiell (modulo) gesucht. Diese Vorgehensweise kann mit jedem Hash-Verfahren kombiniert werden. Offensichtlich werden dabei alle Plätze in HT erreicht:

h0 (K p) = h (K p)

h i (K p) = ( h 0( K p ) - i ) mod m, i = 1, 2, ...

G.Heyer Algorithmen und Datenstrukturen12

Beispiel: Einfüge-Reihenfolge:

BECKETT, HESSE, BÖLL, HAUPTMANN, STEINBECK, SACHS, HAMSUN, SARTRE

HT: m = 8

01234567

Schlüssel Schlüssel01234567

Lösche

G.Heyer Algorithmen und Datenstrukturen13

• Irgendeine Primär- oder Sekundärkollision kann eine Häufung von Primär- oder Sekundärkollision auslösen.

• Löschen: implizit oft Verschiebungen. Entstehende Lücken

in Suchsequenzen sind auszufüllen, da das Antreffen eines

freien Platzes die Suche beendet.

G.Heyer Algorithmen und Datenstrukturen14

Suche in einer Hash-Tabelle bei linearem Sondierenvoid Linsuche (Key X, Hashtab HT, Cardinal m, Cardinal j)

{ /* Suche in HT bei linearem Sondieren */

/*Bei erfolgreicher Suche zeigt j auf Position von X in HT */

Cardinal i;

i = H [X]; /* H sei global definierte Hash-Funktion */

j = i ; /* unbelegter Eintrag in HT sei durch */

/* „ - “ - Zeichen charakterisiert */

while ( (HT [ j ] != X) && (HT[ j ] != „ - „ ) )

{ j = (j -1 ) % m;

if ( i == j)

{ printf ( „ X ist nicht in HT \n“); return ; }

if ( HT [ j ] == „ - „ ) printf („ X ist nicht in HT \n“);

}

return;

}

G.Heyer Algorithmen und Datenstrukturen15

Verbesserung: Modifikation der Überlauffolge(z.B. durch quadratisches Sondieren)

h0 ( K p) = h ( K p)

h i+1 ( K p ) = ( hi ( K p ) + f ( i ) ) mod m oder

h i+1 (K p) = (h i ( Kp ) + f ( i, h ( K p ) ) ) mod m , i= 1, 2, ...

2) Sondieren mit Zufallszahlen

Mit Hilfe eines deterministischen Pseudo-Zufallszahlen-Generators wird die Folge der Adressen [1 ... m-1] mod m genau einmal erzeugt. Abhängig von k wird eine zufällige Hashadresse s(j, k) gewählt.

h0 (K p) = h (K p)

h i (K p) = ( h0 (K p) + z i ) mod m , i = 1, 2, ...

G.Heyer Algorithmen und Datenstrukturen16

3) Double-HashingEinsatz einer zweiten Funktion für die Sondierungsfolge

h0 (Kp) = h (Kp)

hi (Kp) = ( h0 (Kp) + i * h‘ (Kp) ) mod m , i = 1, 2, ...

Dabei ist h‘ (K) so zu wählen, dass für alle Schlüssel K die

resultierende Sondierungsfolge eine Permutation aller

Hash-Adressen bildet.

4) Kettung von Synonymen

• Explizite Kettung aller Sätze einer Kollisionsklasse

verringert nicht die Anzahl der Kollisionsklassen; verkürzt

jedoch den Suchpfad beim Aufsuchen eines Synonyms.

• Bestimmung eines freien Überlaufplatzes

(Kollisionsbehandlung) mit beliebiger Methode

G.Heyer Algorithmen und Datenstrukturen17

Hash-Verfahren mit separatem ÜberlaufbereichDynamische Speicherplatz-Belegung für Synonyme

• Alle Sätze, die nicht auf ihrer Hausadresse unterkommen,

werden in einem separaten Bereich gespeichert.

• Die Bestimmung der Überlaufadresse kann entweder

durch Double Hashing oder durch Kettung der Synonyme

erfolgen.

• Die Synonym-Kettung erlaubt auch die Möglichkeit, den

Speicherplatz für Überläufer dynamisch zu belegen.

• Suchen, Einfügen und Löschen sind auf Kollisionsklasse

beschränkt.

• Unterscheidung nach Primär- und Sekundärbereich

G.Heyer Algorithmen und Datenstrukturen18

Beispiel:

HAYDN *

HT:

m = 7

0

1

2

3

4

5

6

BEETHOVEN

CORELLI

SCHUBERT

MOZART

HÄNDEL *

BACH BRAHMS **

*

*

*

*

* *

LISZT *

*VIVALDI

Schlüssel

G.Heyer Algorithmen und Datenstrukturen19

Analyse des HashingKostenmaße

• = n / m : Belegung von HT mit n Schlüsseln

• Sn = # Suchschritte für das Auffinden eines Schlüssels -

entspricht den Kosten für erfolgreiche Suche und

Löschen (ohne Reorganisation)

• Un = # der Suchschritte für die erfolglose Suche -

das Auffinden des ersten freien Platzes entspricht den

Einfügekosten

Grenzwerte: best case worst case

Sn = 1 Sn = n

Un = 1 Un = n + 1

G.Heyer Algorithmen und Datenstrukturen20

Modell für das lineare Sondieren

• sobald eine gewisse Größe überschreitet, verschlechtert

sich das Zugriffsverhalten sehr stark.

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

• Je länger eine Liste ist, um so schneller wird sie noch

länger werden.

• Zwei Listen können zusammen wachsen (Platz 3 und 14),

so dass durch neue Schlüssel eine Art Verdopplung der

Listenlänge eintreten kann.

G.Heyer Algorithmen und Datenstrukturen21

Ergebnisse für das lineare Sondieren nach Knuth

Sn 0.5 1 + ------- 1

1 - mit 0 = --- < 1 n

mUn 0.5 1 + ---------

1

( 1 - )2

Abschätzung für offene Hash-Verfahren mit optimierter Kollisions-Behandlung

(gleichmäßige HT-Verteilung von Kollisionen)

Sn ~ - --- * ln ( 1 - ) Un ~ -------- 1

1

1 -

G.Heyer Algorithmen und Datenstrukturen22

Anzahl der Suchschritte in HT

10 9 8 7 6 5 4 3 2 1

Sn, Un

0.1 0.3 0.5 0.7 0.9

Un

10 9 8 7 6 5 4 3 2 1

0.1 0.3 0.5 0.7 0.9

Sn Un

Sn

bei linearem Sondieren bei „unabhängiger“ Kollisions-Auflösung

Sn, Un

G.Heyer Algorithmen und Datenstrukturen23

Analyse des Hashing (2)Modell für separate Überlaufbereiche

• Annahme: n Schlüssel verteilen sich gleichförmig über die m möglichen Ketten.

• Jede Synonym-Kette hat also im Mittel n/m = Schlüssel.

Wenn der i-te Schlüssel Ki in HT eingefügt wird, sind in jeder Kette ( i -1 ) / m Schlüssel. Die Suche nach Ki kostet also 1 + ( i -1 ) / m Schritte, da Ki an das jeweilige Ende einer Kette angehängt wird.

Erwartungswert für erfolgreiche Suche:

Sn = 1/n * 1 + ------ = 1 + ------- 1 + - i = 1

n i - 1

m

n - 1

2 * m

2

G.Heyer Algorithmen und Datenstrukturen24

Bei der erfolglosen Suche muss immer die ganze Kettedurchlaufen werden. Die Kostenformel hat somit folgende Struktur:

Un = 1 + 1 * WS ( zu einer Hausadresse existiert ein Überläufer)

+ 2 * WS (zu einer Hausadresse existieren zwei Überläufer)

+ 3 * .....

Un - e -

0.5 0.75 1 1.5 2 3 4 5

Sn 1.25 1.37 1.5 1.75 2 2.5 3 3.5

Un 1.11 1.22 1.37 1.72 2.14 3.05 4.02 5.01

G.Heyer Algorithmen und Datenstrukturen25

Separate Kettung ist auch der „unabhängigen“ Kollisions-Auflösung überlegen.

Hashing ist i. a. ein sehr leistungsstarkes Verfahren. Selbst bei starker Überbelegung ( > 1 ) erhält man bei separater Kettung noch günstige Werte.

G.Heyer Algorithmen und Datenstrukturen26

Dynamische Hash-VerfahrenWachstumsprobleme bei statischen Verfahren

• Statische Allokation von Speicherbereichen:

Speicherausnutzung ?• Bei Erweiterung des Adressraumes: Rehashing

==> Kosten, Verfügbarkeit, AdressierbarkeitS

h

h‘

A

A‘

==> alle Sätze erhalten eine neue Adresse

G.Heyer Algorithmen und Datenstrukturen27

Entwurfsziele

• Eine im Vergleich zu statischen Hashing dynamische

Struktur erlaubt Wachstum und Schrumpfung des

Hash-Bereichs ( Datei )

• keine Überlauftechniken

• Zugriffsfaktor 2 für direkte Suche

Viele konkurrierende Ansätze

• Extendible Hashing ( Fagin et al., 1978 )

• Virtual Hashing und Linear Hashing ( Letwin, 1978, 1980 )

• Dynamic Hashing (Larson, 1978 )

G.Heyer Algorithmen und Datenstrukturen28

ZusammenfassungHash-Funktion

• berechnet Speicheradresse des Satzes

• zielt auf bestmögliche Gleichverteilung der Sätze im

Hash-Bereich

Hashing bietet im Vergleich zu Bäumen eine eingeschränkte

Funktionalität

• direkter Schlüsselzugriff

• i. a. kein sortiert sequentieller Zugriff

• ordnungserhaltendes Hashing nur in Sonderfällen

anwendbar

• statisches Verfahren

G.Heyer Algorithmen und Datenstrukturen29

Idealfall: Direkte Adressierung• nur in Ausnahmefällen möglich ( „dichte“ Schlüsselmenge)

• jeder Satz kann mit einem Zugriff referenziert, eingefügt

oder gelöscht werden

Hash-Verfahren im Hauptspeicher

• Standard: Divisions-Rest-Verfahren

• bei offenen Hash-Verfahren ist der

Belegungsgrad 0.85

dringend zu empfehlen

• Kollisionsbehandlung mit separatem Überlaufbereich

i. a. effizienter und einfacher zu realisieren

G.Heyer Algorithmen und Datenstrukturen30

Erweiterungen: dynamische Hashing-Verfahren

• Reorganisationsfreiheit

• Viele Vorschläge: Erweiterbares Hashing,

Lineares Hashing, ...

( 2 Seitenzugriffe )