Datenstrukturen Sommersemester 2010 Isolde Adler Herzlich willkommen! Organisatorisches Wiederholung Hashing Ankündigungen • Heute gegen Ende der Vorlesung: Studierendenbefragung • Ein Lösungsvorschlag für die klausurtypischen Aufgaben aus der Wiederholungsstunde ist auf den Webseiten erhältlich • Letzte Vorlesungsstunde (13.7.2010): Wiederholungs- & Fragestunde • 29.9.–5.10.2010: Vorsemesterkurs Quick-Start Informatik“ für ” Studienanfänger/innen und Studierende nach dem ersten Jahr. Wiederholung von Schulwissen, Vorbereitung auf die Themen der Informatik Anmeldung: Ab kommender Woche unter www.vorkurs.informatik.uni-frankfurt.de/ Die Teilnehmerzahl ist begrenzt! Isolde Adler Datenstrukturen 2010 2/24 Organisatorisches Wiederholung Hashing (a,b)-Bäume Es gelte a ≥ 2 und b ≥ 2a − 1. Ein Baum T hat die (a, b)-Eigenschaft, falls • alle Blätter von T die gleiche Tiefe haben, • alle Knoten höchstens b Kinder besitzen und • die Wurzel mindestens zwei Kinder hat, während alle sonstigen Knoten mindestens a Kinder haben. • Interessant sind (a, b)-Bäume vor Allem für große Werte von a und b, wenn Daten auf einem Externspeicher abgelegt sind: • Die Tiefe wird dementsprechend klein sein • und wenige der sehr langsamen Zugriffe auf den Externspeicher genügen. • Suchstruktur von (a, b)-Bäumen: verallgemeinert binäre Suchbäume • lookup, insert, remove in O(Tiefe(T )), Tiefe(T ) ist logarithmisch in der Anzahl der Knoten. Isolde Adler Datenstrukturen 2010 3/24 Organisatorisches Wiederholung Hashing Ausblick • Hashing mit Verkettung • Hashing mit offener Adressierung • Cuckoo-Hashing Isolde Adler Datenstrukturen 2010 4/24 Organisatorisches Wiederholung Hashing Hashing – Anwendungen • eine Hashfunktion bildet Elemente aus einem großen Universum in eine kleine Zielmenge ab (die Ausgabe heißt auch Hashcode) • Anwendungen: Hash-Tabellen zum schnellen Suchen in großen Datenmengen • Anwendungen: Kryptographie, etwa für Digitale Signaturen (Prof. Schnorr, Goethe-Universität Frankfurt, hat die berühmte Schnorr-Signatur erfunden.) Isolde Adler Datenstrukturen 2010 5/24 Organisatorisches Wiederholung Hashing Hashing • Sei U die Menge aller möglichen Schlüssel und sei m die Größe einer im Hauptspeicher abspeicherbaren Tabelle. • Eine Funktion h : U → {0, 1, ..., m − 1} heißt eine Hashfunktion. • Zum Beispiel können wir insert (x, info) implementieren, indem wir • h(x) = i berechnen und • (x, info) in Zelle i der Tabelle eintragen. Aber was passiert bei einer Kollision, wenn also Zelle i bereits besetzt ist? Wir beschreiben zwei Hashing-Verfahren, Hashing mit Verkettung und Hashing mit offener Adressierung. Isolde Adler Datenstrukturen 2010 6/24 Organisatorisches Wiederholung Hashing Hashing mit Verkettung Für jede Zelle i wird eine anfänglich leere Liste angelegt. • Jede Liste wird sortiert gehalten. • Für lookup(x): Durchlaufe die Liste von h(x). • Für insert(x) und remove(x): Führe die insert- und remove-Operation für einfach-verkettete Listen aus. Beispiel: Wähle h(x) = (x mod 11) als Hashfunktion. Die Operationen insert(59), insert(18) und insert(125) führen auf die Tabelle 4 - 59 - 125 7 - 18 - - lookup (26) benötigt nur einen Suchschritt: Schlüssel 59 wird gefunden und es wird geschlossen, dass 26 nicht präsent ist. Isolde Adler Datenstrukturen 2010 7/24 Organisatorisches Wiederholung Hashing Die Wahl der Hashfunktion Jeder Schlüssel x wird als Bitvektor dargestellt. Wir können also annehmen, dass x eine natürliche Zahl ist. • Eine beliebte und gute Wahl ist h(x) = x mod m. h(x) kann schnell berechnet werden und wird bei guter“ Wahl von ” m zufriedenstellende Ergebnisse liefern. • Was ist eine schlechte Wahl von m? • Angenommen, m ist eine Zweierpotenz. • Wenn die Schlüssel Charakter-Strings sind, dann werden alle Character-Strings mit gleicher Endung auf dieselbe Zelle gehasht. • Häufig auftretende Endungen provozieren viele Kollisionen und damit lange Listen: Die Bearbeitungszeit der einzelnen Operationen wächst! Wähle stattdessen Primzahlen mit großem Abstand zur nächstliegenden Zweierpotenz. Isolde Adler Datenstrukturen 2010 8/24 Organisatorisches Wiederholung Hashing Wie schnell ist Hashing mit Verkettung? Annahme: es befinden sich n Schlüssel in einer Tabelle mit m Zellen. Wir sagen dann, dass λ = mn der Auslastungsfaktor der Tabelle ist. Wie schnell wird eine insert(x), remove(x) oder lookup(x) Operation ausgeführt? • Bestenfalls ist die Liste für h(x) = i leer und wir erreichen eine konstante Laufzeit. • Schlimmstenfalls sind alle n Schlüssel auf die Liste von i verteilt und die worst-case Laufzeit Θ(n) folgt. Weder best-case noch worst-case Laufzeit scheinen verlässliche Voraussagen der tatsächlichen Laufzeit zu sein. Wir sollten die erwartete Laufzeit betrachten. Isolde Adler Datenstrukturen 2010 9/24 Organisatorisches Wiederholung Hashing Die erwartete Laufzeit I Wir machen die folgenden Annahmen: • jedes Element x ∈ U hat die Wahrscheinlichkeit 1 |U| als Operand in einer Operation aufzutreten. • Die Hashfunktion h streutndie Schlüsselogleichmäßig, d.h. |{x ∈ U | h(x) = i}| ∈ |U| b |U| m c, d m e gilt für jedes i. • Die Hashfunktion h(x) = (x mod m) erfüllt die Streubedingung. • Die Wahrscheinlichkeit pi , dass ein zufällig gezogener Schlüssel auf die Zelle i gehasht wird, ist höchstens pi ≤ d |U| m e ≤ |U| |U| m +1 1 1 ≤ + : |U| m |U| Wie groß ist ni , die Anzahl der Schlüssel für Zelle i? Isolde Adler Datenstrukturen 2010 10/24 Organisatorisches Wiederholung Hashing Die erwartete Laufzeit II L= Pm−1 i=0 pi · ni ist die erwartete Listenlänge. • Wie groß ist L? m−1 X i=0 pi · ni m−1 X m−1 X 1 1 1 1 ≤ + · ni = + · ni m |U| m |U| i=0 i=0 1 1 n = + n =λ+ . m |U| |U| • Da die Hash-Tabelle bereits mit n Schlüsseln belegt ist, gilt n ≤ |U| und n |U| ≤ 1 folgt. • In allen Fällen von praktischer Relevanz wird n sehr viel kleiner als |U| sein und der zweite Bruch kann vernachlässigt werden. Isolde Adler Datenstrukturen 2010 11/24 Organisatorisches Wiederholung Hashing Zusammenfassung • Die erwartete Länge einer Liste für Hashing mit Verkettung ist höchstens 1 + λ. • Die erwartete Laufzeit einer insert-, remove- oder lookup-Operation ist höchstens O(1) + O(λ): Die Hashfunktion ist auszuwerten und dann muss die Hashliste durchlaufen werden. • Hashing mit Verkettung ist ein hochgradig praxistaugliches Verfahren. • Einziger Nachteil: Durch die Verwendung von Listen, und damit durch die Verwendung von Zeigern, entsteht zusätzlicher Speicherbedarf. Isolde Adler Datenstrukturen 2010 12/24 Organisatorisches Wiederholung Hashing Hashing mit offener Adressierung Wir arbeiten mit einer Folge h0 , ..., hm−1 : U → {0, ..., m − 1} von Hashfunktionen. Setze i = 0. (1) Wenn die Zelle hi (x) frei ist, dann füge x in Zelle hi (x) ein. (2) Ansonsten setze i = i + 1 und gehe zu Schritt (1). Die Anzahl der Fehlversuche sollte“ ansteigen, wenn λ zu groß ” wird. Was ist in einem solchen Fall zu tun? • Wenn der Auslastungsfaktor größer als 1/2 wird, dann lade die Tabelle in eine doppelt so große Tabelle. • Die Zeit für die Reorganisation wird durch die schnellere Bearbeitung der Operationen amortisiert. Wie sollen die einzelnen Operationen implementiert werden? Isolde Adler Datenstrukturen 2010 13/24 Organisatorisches Wiederholung Hashing Implementierung von Lookup, Insert und Remove • lookup und insert lassen sich für jede Folge von Hashfunktionen leicht implementieren. • Kopfzerbrechen bereitet remove: Wird nach Einfügen des Schlüssels x in Zelle h1 (x) der Schlüssel in Zelle h0 (x) entfernt, dann hat die Operation lookup (x) ein Problem. • Ist x nicht präsent, weil Zelle h0 (x) leer ist oder • muß weitergesucht werden? • Bringe eine entfernt“ Markierung nach Löschen des Schlüssels in ” Zelle h0 (x) an. Die erwartete Laufzeit einer erfolglosen Suche wird aber anwachsen. Hashing mit offener Adressierung sollte vermieden werden, wenn viele Daten entfernt werden. Isolde Adler Datenstrukturen 2010 14/24 Organisatorisches Wiederholung Hashing Lineares Austesten In der Methode des linearen Austestens wird die Folge hi (x) = (x + i) mod m benutzt: Also wird die jeweils nächste Zelle untersucht. + Für jeden Schlüssel x ist die Folge h0 (x), . . . , hm−1 (x) eine zyklische Verschiebung der Zellen. Insbesondere wird jede Zelle getestet“. ” - Lineares Austesten führt zur Klumpenbildung. • Angenommen, die Daten besetzen ein Intervall {i, i + 1, . . . , j − 1, j} von Zellen. • Wenn ein weiterer Schlüssel x mit h0 (x) ∈ {i, +1, . . . , j − 1, j} eingefügt wird, dann wird x am Ende des Intervalls eingefügt. • Das Intervall wächst und dementsprechend steigt der Aufwand für die einzelnen Operationen. Isolde Adler Datenstrukturen 2010 15/24 Organisatorisches Wiederholung Hashing Doppeltes Hashing Wir benutzen zwei Hashfunktionen f und g und verwenden die Folge hi (x) = (f (x) + i · g (x)) mod m. • Die Klumpenbildung wird vermieden. • Man erhält gute Ergebnisse bereits für f (x) = x mod m und g (x) = m∗ − (x mod m∗ ). • Wähle m als Primzahl und fordere m∗ < m. • g (x) ist stets von Null verschieden. • Wenn f (x) + i · g (x) = f (x) + j · g (x) mod m, dann (i − j) · g (x) = 0 mod m. Also folgt i = j. • Also {hi (x) | 0 ≤ i < m} = {0, . . . , m − 1}. Im doppelten Hashing werden alle Zellen getestet. Isolde Adler Datenstrukturen 2010 16/24 Organisatorisches Wiederholung Hashing Die erwartete Laufzeit einer erfolglosen Suche I Die Annahmen: • Jeder Schlüssel x ∈ U tritt mit Wahrscheinlichkeit 1 |U| als Operand einer Operation auf. • Für jedes x ∈ U ist die Folge (h0 (x), h1 (x), ..., hm−1 (x)) = πx eine Permutation von {0, 1, ..., m − 1} und • Jede Permutation tritt für |U| m! Schlüssel in U auf. • Die letzte Annahme ist nur schwer zu erfüllen und dient nur zur Erleichterung der Analyse. • Wie lange müssen wir auf einen Erfolg, eine freie Zelle, warten? Isolde Adler Datenstrukturen 2010 17/24 Organisatorisches Wiederholung Hashing Die erwartete Laufzeit einer erfolglosen Suche II Man stelle sich vor, dass wir einen Schlüssel zufällig ziehen. Nach der Annahme ist jede Permutation getesteter Zellen gleichwahrscheinlich. • Der Auslastungsfaktor ist λ. • Die Erfolgswahrscheinlichkeit im ersten Versuch ist 1 − λ und steigt in nachfolgenden Versuchen an, da bisher nur besetzte Zellen getestet wurden. • Wie lange müssen wir auf einen Erfolg warten, wenn die Erfolgswahrscheinlichkeit eines einzigen Versuchs mindestens p = 1 − λ ist? • Mit Wahrscheinlichkeit höchstens (1 − p)k · p werden k + 1 Versuche benötigt. • Die erwartete Zeit bis zum ersten Erfolg beträgt höchstens P∞ k=0 (k + 1) · (1 − p)k · p = p1 . Die erwartete Anzahl getesteter Zellen ist höchstens Isolde Adler Datenstrukturen 2010 18/24 1 1−λ . Organisatorisches Wiederholung Hashing Zusammenfassung Der Auslastungsfaktor sei λ. • Hashing mit Verkettung besitzt für alle Operationen eine erwartete Laufzeit von höchstens O(1) + λ. • Wegen der Klumpenbildung des linearen Austestens werden die Operationen bei hoher Auslastung sehr langesm Allerdings ist lineares Austesten cache-freundlich“. ” • Die erwartete Laufzeit einer erfolglosen Suche für doppeltes Hashing 1 ist höchstens 1−λ . Der Auslastungsfaktor für das lineare Austesten oder das doppelte Hashing sollte nicht zu groß werden: Lade in eine doppelt so große Tabelle, wenn λ > 1/2. Animation Isolde Adler Datenstrukturen 2010 19/24 Organisatorisches Wiederholung Hashing Cuckoo Hashing I Arbeite mit zwei Hashtabellen T1 und T2 sowie zwei Hashfunktionen h1 undh2 . • Insert(x): Wiederhole bis zu M mal, • Speichere x in Tabelle T1 und Zelle h1 (x) ab. • Wenn die Zelle h1 (x) in Tabelle T1 durch einen Schlüssel y belegt war, dann füge y in Tabelle T2 und Zelle h2 (y ) ein. • Wenn die Zelle h2 (y ) in Tabelle T2 durch einen Schlüssel z belegt war, dann setze x = z und beginne eine neue Iteration. • Lookup(x): Überprüfe Zelle h1 (x) in Hashtabelle T1 und gegebenenfalls Zelle h2 (x) in Hashtabelle T2 . • Remove(x): Wenn x vorhanden ist, dann entferne x aus Zelle h1 (x) in Hashtabelle T1 oder aus Zelle h2 (x) in Hashtabelle T2 . Warum der Name Cuckoo Hashing? Eine Kuckuck Art wirft ein oder mehrere Eier aus einem fremden Nest und legt ein eigenes Ei hinzu. Isolde Adler Datenstrukturen 2010 20/24 Organisatorisches Wiederholung Hashing Cuckoo Hashing II • Cuckoo Hashing hasht direkt in die Tabellen. Die remove-Operation ist aber mit Leichtigkeit implementierbar. • Eine worst-case Garantie für lookup und remove: Höchstens zwei Zellen werden inspiziert. • Nur die insert-Operation ist komplizierter: • Beachte, dass der Auslastungsfaktor λ durch 21 beschränkt ist. • Es kann gezeigt werden, dass die erwartete Anzahl getesteter Zellen 1 höchstens O(1 + 0.5−λ ) beträgt. • Wenn die insert Prozedur nach M Iterationen nicht erfolgreich ist, dann wird der zuletzt herausgeworfene Schlüssel in einer Liste von ” Fehlversuchen“ abgelegt. • Welche Hashfunktionen? Wähle 0 < a1 , a2 , a3 < m · 2w zufällig und setze h(x) = fa1 (x) ⊕ fa2 (x) ⊕ fa3 (x), wobei fa (x) = (a · x mod m · 2w ) div 2w . Isolde Adler Datenstrukturen 2010 21/24 Organisatorisches Wiederholung Hashing Zusammenfassung Der Auslastungsfaktor sei λ. • Hashing mit Verkettung besitzt für alle Operationen eine erwartete Laufzeit von höchstens O(1) + λ. • Wegen der Klumpenbildung des linearen Austestens werden die Operationen bei hoher Auslastung sehr langsam. Allerdings ist lineares Austesten cache-freundlich“. ” • Die erwartete Laufzeit einer erfolglosen Suche für doppeltes Hashing 1 ist höchstens 1−λ . Der Auslastungsfaktor für das lineare Austesten oder das doppelte Hashing sollte nicht zu groß werden: Lade in eine doppelt so große Tabelle, wenn λ > 1/2. • Die erwartete Anzahl getesteter Zellen für insert bei Cuckoo Hashing ist höchstens 21 (1 + 1 0.5−λ ). Höchstens zwei Zellen werden für lookup- oder remove inspiziert. Animation Isolde Adler Datenstrukturen 2010 22/24 Organisatorisches Wiederholung Hashing Universelles Hashing • Für jede Hashfunktion, ob für Hashing mit Verkettung oder für Hashing mit offener Addressierung kann eine worst-case Laufzeit von Θ(n) erzwungen werden. Wir müssen also Glück“ haben, dass unsere Operationen kein ” worst-case Verhalten zeigen. • Stattdessen arbeiten wir mit einer Klasse H von Hashfunktionen: • Zu Beginn der Berechnung wählen wir zufällig eine Hashfunktion h∈H • und führen Hashing mit Verkettung mit der Hashfunktion h durch. • Warum sollte“ ein solches Verfahren funktionieren? ” • Eine einzelne Hashfunktion ist durch eine bösartig gewählte Operationenfolge zum Scheitern verurteilt, • aber die meisten Hashfunktion werden diese Operationenfolge mit Bravour meistern. • Was ist eine geeignete Klasse H? Isolde Adler Datenstrukturen 2010 23/24 Organisatorisches Wiederholung Hashing c-universelle Klassen von Hashfunktionen Eine Menge H ⊆ {h | h : U → {0, ..., m − 1}} ist c-universell, falls c |{h ∈ H | h(x) = h(y )}| ≤ |H| m für alle x, y ∈ U mit x 6= y gilt. Wenn H c-universell ist, dann gibt es keine zwei Schlüssel, die mit Wahrscheinlichkeit größer als mc auf die gleiche Zelle hashen. • Gibt es c-universelle Klassen von Hashfunktionen für kleine Werte von c • und können wir dann für jede Operationenfolge lookup, insert und remove hochwahrscheinlich schnell ausführen? Isolde Adler Datenstrukturen 2010 24/24