Suchalgorithmen Contents Pierre Fierz Suchalgorithmen Pierre Fierz Chapter 4 Ungeordnete Suchstruktur Suchalgorithmen 1 Ungeordnete Suchstruktur Implementation als Hashtabelle Implementation als Hashtabelle Universelles Hashing Universelles Hashing Lecture Algorithmen & Datenstrukturen 20.10.2011 Geordnete Suchstruktur Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als 2-3-4-Baum 2 Geordnete Suchstruktur Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Pierre Fierz Berner Fachhochschule Technik und Informatik 4.1 Outline Suchalgorithmen 4.2 Einführung Pierre Fierz 1 Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Pierre Fierz Ungeordnete Suchstruktur Ungeordnete Suchstruktur • Eine Suchstruktur (auch assoziativer Array genannt) ist ein Implementation als Hashtabelle abstrakter Datentyp. Universelles Hashing Geordnete Suchstruktur • Der Typ besteht aus einer Ansammlung von Paaren der Implementation als sortierter Array Form (Schlüssel, Daten). Implementation als 2-3-4-Baum 2 Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Suchalgorithmen • Ein Schlüssel darf in der Struktur nur einmal vorkommen. Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Die Schlüssel sind in keiner vorgegebenen Reihenfolge gespeichert. • Die Operationen des assoziativen Arrays sind: Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Suchen der Daten über den assozierten Schlüssels • Einfügen eines Schlüssels und der assozierten Daten • Löschen eines Schlüssels und der assozierten Daten. 4.3 4.4 Einführung 2 Suchalgorithmen Pierre Fierz Beispiel: Compiler • Ein Beispiel für einen assoziativen Array ist die Symboltabelle eines Compilers. • Der Schlüssel ist ein Identifier und die Daten sind Informationen wie Art, Datentyp, Scope usw. Interface Assoziativer Array Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Beispiel: Datenbanken Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree • In relationalen Datenbanken hat jedes Tuple in der Tabelle Spezifikation in Java • Das Folgende Java-Interface spezifiziert einen assoziativen Array. Implementation als Skipliste einen eindeutigen Schlüssel. • Zum Testen der Eindeutigkeit eignet sich ein assoziativer Array sehr gut. • Ferner kann der Schlüssel auch zum Durchführen von Joinoperationen benutzt werden. 1 /** 2 * Dieses Interface spezifiziert einen assoziativen Array 3 * 4 */ 5 public interface AssocArray<K,D> { 6 /** 7 * Gibt die Anzahl Elemente im Array zurück 8 * 9 * <pre> 10 Preconditions: none * 11 Postconditions: none * 12 </pre> * 13 * 14 * @return Anzahl der Elemente im Array 15 */ 16 public int cardinality(); 17 18 /** 19 * Sucht einen Schlüssel im Array 20 * 21 * <pre> 22 Preconditions: none * 23 Postconditions: none * 24 * </pre> 25 * 26 * @param key dieser Schlüssel wird gesucht 27 * 28 * @return true falls der Schluessel gefunden wurde 29 * 30 */ 31 public boolean contains(K key); Suchalgorithmen Pierre Fierz Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 4.5 Spezifikation in Java 2 Suchalgorithmen 4.6 Spezifikation in Java 3 Pierre Fierz Suchalgorithmen Pierre Fierz • Fortsetzung Interface Assoziativer Array 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 /** * Sucht einen Schlüssel in der SuchStruktur * und gibt die assozierten Daten zurück. * * <pre> Preconditions: none; * Postconditions: none * * </pre> * * @param key dieser Schlüssel wird gesucht * * @return Die Daten zum gefundenen Schlüssel * * @throws NotInTableException Falls der Schlüssel nicht existiert * */ public D find(K key) throws NotInTableException; Ungeordnete Suchstruktur • Fortsetzung Implementation als Hashtabelle Universelles Hashing Interface Assoziativer Array Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste /** * Löscht einen Schlüssel aus der assoziativen Array. * Keine Aktion, falls der Schlüssel nicht gefunden wird. * * <pre> Preconditions: none * Postconditions: new.contains(key) == false * * </pre> * */ public void remove(K key); 4.7 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 } Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur /** * Einfügen eines neuen Schlüssels. * * <pre> Preconditions: contains(key) == false * Postconditions: new.contains(key) == true * * </pre> * * @param key dieser Schluessel wird eingefuegt * @param data die zum Schluessel assozierten Daten * * @throws InTableException Falls der Schlüssel schon vorhanden * */ public void insert(K key, D data) throws InTableException; Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 4.8 Suchalgorithmen Implementation als Hashtabelle Hashing: Begriffe Pierre Fierz Pierre Fierz • Die Menge der möglichen Schlüssel KeySet • Die Art und Anzahl der möglichen Schlüssel ist von der Applikation abhängig. • Die Anzahl Elemente in dieser Menge kann sehr gross werden. • Beispiel: Schlüssel bestehen aus 10 grossen Buchstaben ⇒ |KeySet| = 2610 • Die Hashtabelle • Der assoziative Array kann als Hashtabelle implementiert werden. • Die Schlüssel werden in einem Array gespeichert. • Durch eine arithmetische Transformation des Schlüssels wird der Index im Array gesucht. Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als 2-3-4-Baum Hashtabelle Key Keymenge Ungeordnete Suchstruktur Implementation als sortierter Array Die Hashtabelle Hashfunktion Hashadressen Pointer auf Daten 0 1 2 3 Suchalgorithmen Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree • Ein Array mit einer fixen Länge N. • Vergrössern des Arrays ist eine aufwendige Operation. Implementation als Skipliste Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Die Hashfunktion • Die Hashfunktion ist eine Abbildung: Hash : KeySet 7→ {0, 1, 2 . . . N − 1} • Die Funktion Hash bildet einen Schlüssel k ∈ KeySet auf einen Index der Hashtabelle ab. • Der Wert der Funktion Hash(k ) heisst die Hashadresse des Schlüssels k . N−2 N−1 4.9 Hashing: Begriffe 2 Suchalgorithmen 4.10 Die Wahl der Hashfunktion Pierre Fierz Pierre Fierz • Die Hashfunktion muss: • leicht zu berechnen sein • die Anzahl Kollisionen minimieren • die Schlüssel möglichst gut auf die ganze Tabelle verteilen. Ungeordnete Suchstruktur • Kollisionen • Normalerweise gilt: |KeyMenge| N • Das bedeutet, dass Hash i.A. nicht bijektiv ist. • Wenn zwei verschiedene Schlüssel k1 , k2 ∈ KeySet dieselbe Hashadresse haben, so bezeichnet man dies als Kollision • Schlüssel k1 und k2 heissen Synonyme bezüglich der Funktion Hash. • Beim Auftreten einer Kollision müssen trotzdem beide Schlüssel in die Tabelle eingetragen werden. • Die Art und Weise wie dieses Problem gelöst wird, hat einen grossen Einfluss auf die Effizienz des Suchprozesses. Suchalgorithmen Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur • Um diese Forderungen zu erfüllen, muss die Hashfunktion Implementation als sortierter Array die beiden folgenden Kriterien erfüllen Implementation als 2-3-4-Baum Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Kriterien für die Hashfunktion Implementation als Rot-Schwarz-Baum Implementation als Splay Baum 1 Implementation als B-Tree Implementation als Skipliste 2 Der Funktionswert muss von allen Zeichen des Schlüssels abhängig sein. Die Hashfunktion muss die Schlüssel gleichmässig über den gegebenen Indexbereich der Tabelle verteilen. Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Das heisst, wird k ∈ KeyMenge zufällig ausgewählt, so ist die Wahrscheinlichkeit, dass Hash(k ) = i ist, gleich 1/Tabellenplätze. 4.11 4.12 Suchalgorithmen Die Wahl der Hashfunktion 2 Suchalgorithmen Die Wahl der Hashfunktion 3 Pierre Fierz • Wir berechnen die Hashfunktion in zwei Schritten: 1 Die erste Operation besteht darin, den Schlüssel auf eine Integerzahl (kann auch negativ sein) abzubilden. Dieser Wert heisst Hashcode. 2 Die zweite Operation besteht darin, den Hashcode auf einen Index abzubilden, der im Range unserer Hashtabelle liegt. Diese Operation heisst Kompression. Pierre Fierz • Der Hashcode sollte möglichst wenige Kollisionen produzieren Ungeordnete Suchstruktur Geordnete Suchstruktur Implementation als sortierter Array Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Beliebige Schlüssel Implementation als Hashtabelle Wir können schliesslich jeden Key als k-Tuple (x0 , x1 , . . . , xk −1 ) von Integers (oder von Bytes) auffassen. Nun können wir alle diese Zahlen Zusammenzählen und erhalten als Hashcode Universelles Hashing Implementation als 2-3-4-Baum Hashcode und Kompression Ungeordnete Suchstruktur Summieren der Komponenten Implementation als Hashtabelle HashCode(key ) = Implementation als B-Tree Implementation als Skipliste Hashcode k −1 X Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum xi i=0 Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Diese Methode ist nicht gut, da die Reihenfolge der Zeichen nicht berücksichtigt wird. −2 −1 0 1 2 • Als Beispiel sehen wir, dass die Strings temp01 und Kompression temp10 den gleichen Hashcode erhalten. 0 • In der Englischen sprache kollidieren alle folgenden N−1 Wörter stop, tops, pots und spot. 4.13 Suchalgorithmen Die Wahl der Hashfunktion 4 4.14 Die Wahl der Hashfunktion 5 Pierre Fierz Suchalgorithmen Pierre Fierz Beispiel: Berechnen des polynomialen Hashcode • Wir machen jetzt einen 2. Versuch Ein besserer Hashcode erhält man, wenn wir die Reihenfolge der der xi ’s im k-Tuple key = (x0 , . . . , xk −1 ) berücksichtigen. Wir erhalten nun den folgenden Hashcode: HashCode(key ) = x0 a key = HANS a = 33 Wenn wir den ASCII-Code verwenden gilt nun: Ungeordnete Suchstruktur Polynomialer Hashcode k −1 + x1 a k −2 + · · · + xk −2 a + xk −1 Implementation als Hashtabelle Universelles Hashing (x0 , x1 , x2 , x3 ) = (72, 65, 78, 83) Geordnete Suchstruktur Mit diesen Angaben können wir nun den Hashcode für den Schlüssel HANS berechnen: Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Nach Horn’s Regel kann dies folgendermassen umgeschrieben werden: Ungeordnete Suchstruktur Implementation als Splay Baum HashCode(HANS) = 83 + 33(78 + 33(65 + 33 · 72)) = 2660906 Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste HashCode(key ) = xk −1 + a(xk −2 + a(xk −3 + · · · + a(x2 + a(x1 + ax0 ))...)) • Welchen Wert sollen wir nun für a wählen? • Im Buch von Goodrich und Tamassia werden 33, 37, 39 oder 41 empfohlen. • Mathematisch gesehen ist das die Auswertung eines • In einem Experiment wurde der Hashcode von 50’000 verschiedenen Polynoms mit den Koeffizienten xk −1 . . . x0 an der Stelle a. Englischwörter berechnet. • Daher heisst dieser Code auch polynomialer Hashcode • Mit der Wahl von a als 33, 37, 39 oder 41 gab es in allen Fällen weniger als 7 Kollisionen. 4.15 4.16 Suchalgorithmen Die Wahl der Hashfunktion 6 Pierre Fierz • Wir müssen jetzt noch die Kompressionsfunktion bestimmen Beispiel: Kollisionen Ungeordnete Suchstruktur Die Divisionsmethode das Intervall [0 . . . N − 1] abildet (N ist die Länge der Tabelle • Im allgemeinen werden hier auch Kollisionen auftreten, da die Tabelle normalerweise kleiner ist als das ganze Intervall des Hashcodes. • Für die Kompression des Hashcodes (hc) können wir die folgende einfache Funktion anwenden Universelles Hashing Pierre Fierz Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Geordnete Suchstruktur In diesem Fall wird jeder Hashcode mit drei anderen Hashcodes kollidieren. Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Wählen wir hingegen N = 101 (eine Primzahl), so entsteht überhaupt keine Kollision. Implementation als Skipliste Hash(hc) = |hc| Suchalgorithmen Ungeordnete Suchstruktur N = 100 HashCodes = {200, 205, 215, 220, . . . , 600}. Implementation als Hashtabelle • Wir müssen eine Funktion finden, die den HashCode auf Die Wahl der Hashfunktion 7 • Wir wollen noch Beispiele ansehen wie Kollisionen entstehen Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Beispiel: Der Fall N = 2k mod N • Falls N die Form N = 2k hat so ist die Hashadresse nur von den letzten k Bits des Hashcodes abhängig. • Bei der Divisionsmethode ist die Wahl der Tabellenlänge N kritisch. • Das heisst, die Hashadresse ist nur von einem Teil des Hashcodes abhängig. • Eine wirklich gute Verteilung der Haschcodes auf das Intervall [0 . . . N − 1] erhält man nur, wenn N eine Primzahl ist. • In diesem Fall wird die Verteilung auf die Tabelle nicht unbedingt gut sein. 4.17 Die Wahl der Hashfunktion 8 Suchalgorithmen 4.18 Behandlung von Kollisionen: Separat chaining Pierre Fierz Pierre Fierz • Wir wollen noch eine bessere Alternative für die Wahl der Kompression angeben • In jedem Element der Hashtabelle wird der Kopf einer Ungeordnete Suchstruktur verketteten Liste gespeichert. Implementation als Hashtabelle Die MAD-Methode • In der Liste sind alle Synonyme dieser Hashadresse Universelles Hashing • MAD steht für multiply add and divide und ist eine bessere Methode den Hashcode zu komprimieren. h(hc) = |a · hc + b| mod N gespeichert. Geordnete Suchstruktur Implementation als sortierter Array Implementation als B-Tree Implementation als Skipliste Implementation als Hashtabelle Universelles Hashing Implementation als sortierter Array Hash(Fritz) = Hash(Paul) = Hash(Hans) = Hash(Peter) Implementation als Rot-Schwarz-Baum Ungeordnete Suchstruktur Geordnete Suchstruktur Beispiel: Separat chaining Implementation als 2-3-4-Baum Fritz Paul Gerda Hash(Gerda) = Hash(Sami) Sami Carmen Gina Implementation als Splay Baum • N ist eine Primzahl und a und b sind positive ganze Suchalgorithmen Hans Peter Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Zahlen, die bei der Bestimmung der Funktion zufällig ausgewählt werden. • Natürlich muss (a mod N) 6= 0 gelten, da sonst der Wert der Funktion immer (b mod N) ist. Hash(Carmen) = Hash(Gina) = Hash(Herbert) Herbert • Diese Funktion verteilt die Werte einer Menge von Hashcodes fast gleichmässig auf das Intervall [0, N − 1]. 4.19 4.20 Behandlung von Kollisionen: Separat chaining 2 Suchalgorithmen Pierre Fierz • Die Operationen sehen folgendermassen aus. Ungeordnete Suchstruktur Hashtabellen Operationen Implementation als Hashtabelle Einfügen von k : Die Hashadresse ha = Hash(k ) wird berechnet. Der Schlüssel k wird am Ende der Liste mit Index ha angehängt. Suchen von k : Die Hashadresse ha = Hash(k ) wird berechnet In der Liste mit Index ha wird sequentiell nach k gesucht. Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Behandlung von Kollisionen: double hashing • Bei double hashing verwenden wir zwei verschiedene Hashfunktionen Hash1 und Hash2 . • ha = Hash1 (k ) berechnet die HashAdresse des Schlüssels k . • offset = Hash2 (k ) berechnet einen Offset. Dieser wird bei einer Kollision verwendet um den nächsten freien Platz in der Tabelle zu finden. Implementation als Rot-Schwarz-Baum Pierre Fierz Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Beispiel: double hashing Implementation als 2-3-4-Baum Suchalgorithmen Implementation als 2-3-4-Baum Hash(Fritz) = Hash(Paul) = A0 Implementation als Splay Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als B-Tree Implementation als Skipliste Löschen von k : Die Hashadresse ha = Hash(k ) wird berechnet In der Liste mit Index ha wird sequentiell nach k gesucht. Falls k in der Liste gefunden wird, Element aus der Liste entfernen. A0 Fritz (A0 + 1 * Hash2(Paul)) mod N Gerda (A0 + 2 * Hash2(Paul)) mod N Paul Implementation als Skipliste Carmen 4.21 Behandlung von Kollisionen: double hashing 2 Suchalgorithmen 4.22 Behandlung von Kollisionen: double hashing 3 Pierre Fierz Pierre Fierz Hashtabellen Operationen (Forts.) Hashtabellen Operationen Suchen von k : Einfügen von k : 1 Die Hashadresse ha = Hash(k ) wird berechnet. 2 Ist der Tabellenplatz leer, so wird der Schlüssel k dort eingetragen. 3 Ist der Tabellenplatz nicht leer, so wird bei den Adressen (Hash1 (k ) + Hash2 (k )) mod N (Hash1 (k ) + 2 · Hash2 (k )) mod N (Hash1 (k ) + 3 · Hash2 (k )) mod N ... weitergesucht, bis ein leerer Platz gefunden wird. 1 Die Hashadresse ha = Hash1 (k ) wird berechnet. Ungeordnete Suchstruktur 2 Ist der Schlüssel k an der Adresse ha gespeichert, ist die Suche Implementation als Hashtabelle erfolgreich. Universelles Hashing Geordnete Suchstruktur oder ist der Platz gelöscht, so wird bei den Adressen Implementation als sortierter Array (Hash1 (k ) + Hash2 (k )) mod N (Hash1 (k ) + 2 · Hash2 (k )) mod N (Hash1 (k ) + 3 · Hash2 (k )) mod N ... Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing 3 Ist der Tabellenplatz bei ha durch einen anderen Schlüssel als k besetzt 4 Der Schlüssel k wird an dieser Stelle eingefügt. Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste weitergesucht. 4 Die Suche wird abgebrochen wenn: 5 Die Suche nach einem freien Platz wird abgebrochen, wenn gilt: (Hash1 (k ) + n · Hash2 (k )) Suchalgorithmen i) Der Schlüssel k wird gefunden: erfolgreiche Suche ii) Ein leerer Platz wird gefunden: erfolglose Suche iii) es gilt: mod N = Hasch1 (k ) 6 Damit beim Suchen eines leeren Platzes alle Elemente der Tabelle brücksichtigt werden muss gelten: (Hash1 (k ) + n · Hash2 (k )) ∀k : ggt(Hash2 (k ), N) = 1 mod N = Hash1 (k )) erfolglose Suche. 4.23 4.24 Suchalgorithmen Behandlung von Kollisionen: double hashing 4 Suchalgorithmen Wahl der zweiten HashFunktion Hash2 (k ) Pierre Fierz Pierre Fierz • Hier noch ein Beispiel von Suchen mit double Hashing • Man sieht sehr schön die Problematik bei gelöschten Elementen. • Wir betrachten für Hash2 zwei Möglichkeiten: Ungeordnete Suchstruktur Implementation als Hashtabelle 1 Universelles Hashing Beispiel: Suchen mit double hashing • Beim linear probing treten die Schlüssel in der Tabelle in Implementation als 2-3-4-Baum A0 Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste (A0 + 1 * Hash2(Paul)) mod N Gerda (A0 + 2 * Hash2(Paul)) mod N Gelöscht 2 Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Hash2 (k ) = (N − 2) − (|HashCode(k )| mod (N − 2)) • Diese Funktion hat sich in der Praxis bewährt. • Falls N eine Primzahl ist, dann gilt: ggt(Hash2 (k ), N) = 1 • Die Idee ist die folgende: Falls Hash1 (k1 ) = Hash1 (k2 ), so Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste gilt im allgemeinen Hash2 (k1 ) 6= Hash2 (k2 ) Weitersuchen • Dies verhindert die Bildung von Bündeln wie sie beim Carmen (A0 + 3 * Hash2(Paul)) mod N Bündeln auf. • Die Belegung der Tabelle ist also nicht ideal Implementation als Rot-Schwarz-Baum Fritz Universelles Hashing sondern von linear probing (lineares Sondieren). Implementation als sortierter Array Hash(Fritz) = Hash(Paul) = A0 Implementation als Hashtabelle Hash2 (k ) = 1 ∀k ∈ KeyMenge • In diesem Fall spricht man nicht von double hashing Geordnete Suchstruktur Ungeordnete Suchstruktur linearen Sondieren auftreten. leer Platz leer Paul nicht gefunden 4.25 Suchalgorithmen Vergleich der Methoden 4.26 Suchalgorithmen Vergleich der Methoden 2 Pierre Fierz • Die Anzahl Vergleiche, die nötig sind um einen Schlüssel zu suchen, sind vom Loadfactor α der Tabelle abhängig. • Ist N die Grösse der Tabelle und M die Anzahl gespeicherter Schlüssel, so definieren wir: Pierre Fierz Beispiel: Anzahl Zugriffe beim hashing Ungeordnete Suchstruktur Implementation als Hashtabelle Ungeordnete Suchstruktur Eine Hashtabelle sei zu 90% gefüllt d.h. α = 0.9. Universelles Hashing Universelles Hashing Geordnete Suchstruktur Geordnete Suchstruktur Vergleiche für eine erfolglose Suche: Implementation als sortierter Array α = M/N Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum • In der nächsten Tabelle sind die durchnittlichen Anzahl Vergleiche für die drei Methoden angegeben. Methode Separat chaining Linear probing Erfolglose Suche 1+α 1 1 (1 + (1−α) 2 ) falls α 6= 1 2 Erfolgreiche Suche 1+ α 2 1 1 (1 + (1−α) ) falls α 6= 1 2 Double hashing 1 1−α − falls α 6= 1 ln(1−α) α Implementation als Hashtabelle Implementation als Splay Baum Separatchaining Linearprobing Doublehashing Implementation als B-Tree Implementation als Skipliste 4.27 = 1.9 = 50.5 = 10.0 = = = 1 + 0.45 = 1 1 (1 + ) = 2 0.1 − ln(0.1) = 0.9 Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Vergleiche für eine erfolgreiche Suche: Separatchaining Linearprobing Doublehashing falls α 6= 1 = 1 + 0.9 1 ) = 12 (1 + (0.01) 1 = 0.1 1.45 5.5 2.6 4.28 Universelles Hashing Suchalgorithmen Universelles Hashing 2 Pierre Fierz Pierre Fierz • Wir wollen zum Schluss noch Betrachtungen zur Hashfunktion anstellen. • Es geht darum Familien von universellen Hashfunktionen zu finden. • Im folgenden setzten wir immer voraus, dass die Kollisionsbehandlung mittels separat chaining geschieht. Eigenschaften für ein gutes Hashing • Mit den vorherigen Voraussetzung können wir die Ungeordnete Suchstruktur Komplexität der Operationen bestimmen. Implementation als Hashtabelle • Für das Suchen, Einfügen und Löschen eines Element x Universelles Hashing ist die Komplexität: Geordnete Suchstruktur Implementation als sortierter Array O(Länge der Liste beih(x)) Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum • Wichtig ist also eine Analyse der Länge dieser Listen. Implementation als B-Tree 1 Die Schlüssel sollen gut (regelmässig) in der Hashtabelle verteilt sein, damit möglichst wenig Kollisionen entstehen. 2 Falls in einer Tabelle n Schlüssel gespeichert werden, sollte die Tabellengrösse N = O(n) sein, damit nicht zu viel Platz verlorengeht. 3 Die Hashfunktion ist in Zeit O(1) berechenbar. Suchalgorithmen Implementation als Skipliste Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Intuition: Implementation als Skipliste Eine gute Verteilung der Schlüssel in der Tabelle wird mit Hilfe eines Randomgenerators erreicht. Dieser Ansatz ist aber nicht möglich, da wir dann die Schlüssel nie mehr finden könnten. Also muss man versuchen die Hashfunktion h so zu wählen, dass diese “pseudorandom” ist. 4.29 Universelles Hashing 3 Suchalgorithmen 4.30 Universelles Hashing 4 Pierre Fierz • Schlechte Nachricht für unser Vorhaben • Sei U die Menge der möglichen Schlüssel, M die Anzahl Schlüssel in der Tabelle und N die Grösse der Tabelle, dann gilt der folgende Satz: Theorem Für eine beliebige Hashfunktion h gilt: Falls |U| ≥ (M − 1)N + 1 ist, so existiert eine Menge S ⊂ U mit |S| = M, dessen Elemente alle dieselbe Hashadresse besitzen. Suchalgorithmen Pierre Fierz Ungeordnete Suchstruktur • Wir möchten garantieren, dass Hashing für alle Implementation als Hashtabelle Schlüsselmengen S “gut” ist. Universelles Hashing Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing • Dazu verwenden wir die Wahrscheinlichkeit (in Analogie Geordnete Suchstruktur zu randomized Quicksort). Implementation als sortierter Array • Die Idee ist, bei der Konstruktion der Hashfunktion h Implementation als 2-3-4-Baum Randomnumber zu benutzen. Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Die dabei entstehende Hashfunktion h selbst ist deterministisch. Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Wir werden zeigen, dass für jede Menge S von Schlüsseln und einer mit Randomnumbers konstruierten Funktion h der Erwartungswert des Resultats gut ist. • Aus diesem Grund erscheint Hashing oft mysteriös. • Wie kann man behaupten Hashing sei gut, wenn jede • Diese Technik heisst universelles Hashing. Hashfunktion durch eine geschikte Wahl der Schlüssel “überlistet” werden kann? 4.31 4.32 Universelle Familie von Hashfunktionen Suchalgorithmen Universelle Familie von Hashfunktionen 2 Pierre Fierz Pierre Fierz • Wir nehmen ohne Einschränkung der Allgemeinheit an, dass die Schlüssel ganze Zahlen im Bereich U = [0, K − 1] sind. • Die entsprechenden Hashfunktionen sind dann Funktionen der Form • Der folgende Satz liefert das von uns gewünschte Resultat Theorem Ungeordnete Suchstruktur Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum . Ungeordnete Suchstruktur Falls H eine universelle Familie von Hashfunktionen ist, so gilt für jede Teilmenge S ⊆ U mit |S| = M, jedes Element x ∈ U und einer zufällig aus H ausgewählten Funktion h, dass der Erwartungswert einer Kollision von x mit anderen Elementen aus S höchstens M N. Implementation als Hashtabelle Universelles Hashing h : [0, K − 1] → [0, N − 1] Implementation als Rot-Schwarz-Baum Implementation als B-Tree Eine Menge H von Hashfunktionen der Form h : [0, K − 1] → [0, N − 1] heisst universell (oder universelle Familie von Funktionen), falls für alle j, k ∈ [0, K − 1] mit j 6= k und für eine zufällig aus H gewählte Funktion gilt: Pr (h(j) = h(k )) ≤ Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Definition Suchalgorithmen Implementation als Skipliste Implementation als Splay Baum Proof. Implementation als B-Tree • Sei Cxy = 1 falls x und y kollidieren sonst 0. • Cx sei die Summe aller Kollisionen von x also gilt Implementation als Skipliste P Cx = y ∈S,x6=y Cxy . • Weil H universell ist gilt, dass E[Cxy ] = Pr (x und y kollidieren) ≤ N1 • Die Linearität des Erwartungswertes ergibt: P E[Cx ] = y ∈S,x6=y E[Cxy ] ≤ M N 1 N Pr steht für “Probability”. 4.33 Universelle Familie von Hashfunktionen 3 Suchalgorithmen Pierre Fierz 4.34 Universelle Familie von Hashfunktionen 4 • Es bleibt noch zu zeigen, dass man universelle Familien Suchalgorithmen Pierre Fierz von Hashfunktionen konstrieren kann. • Aus dem vorherigen Satz und der Tatsache, dass wir separat chaining verwenden folgt: • Das Suchen, Einfügen oder Löschen eines Schlüssels ist proportional zur Anzahl der Kollisionen. • Das Berechenen des Schlüssels ist O(1). Damit erhalten wir für alle drei Operationen den Zeitaufwand: M M O 1+ =O N N • Wir verwenden dazu das Matrixverfahren. Ungeordnete Suchstruktur Das Matrix-Verfahren Implementation als Hashtabelle Implementation als Hashtabelle Länge der Keys sei u−Bits Länge der Tabelle N hat die Form N = 2b Wir wählen die Funktion h als eine zufällige u × b Matrix von 0 und 1. Dann gilt: h(x) = h~x Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Anders ausgedrückt heisst das: Ungeordnete Suchstruktur wobei alle Additionen Modulo 2 durchgeführt werden. Die Menge H besteht aus allen u × b (0/1) Matritzen. Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Beispiel: Universelle Haschfunktion die Komplexität der Operationen ist proportional zum Loadfaktor der Tabelle. 1 0 1 4.35 0 0 1 1 1 1 1 0 1 0 1 1 1 = 0 0 0 4.36 Universelle Familie von Hashfunktionen 5 Suchalgorithmen Universelle Familie von Hashfunktionen 6 Pierre Fierz Pierre Fierz Theorem Für das Matrix-Verfahren gilt: Für h ∈ H und x, y ∈ U mit x 6= y gilt: Pr [h(x) = h(y )] = 1 1 = b N 2 Anders ausgedrückt: H ist eine universelle Familie von Hashfunktionen. Proof. (Forts.) Ungeordnete Suchstruktur Implementation als Hashtabelle • Wir betrachten nun x, y ∈ U mit x 6= y . Universelles Hashing Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing • i sei die erste Komponente wo x un y nicht Geordnete Suchstruktur übereinstimmen. Wir nehmen o.B.d.A. an, dass xi = 0 und yi = 1. Implementation als sortierter Array Implementation als 2-3-4-Baum • Nun wählen wir alle Kolonnen von h ausser der i-ten aus Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Proof. Suchalgorithmen • Bei der Wahl der i − ten Kolonne ändert aber h(x) nicht da xi = 0. Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Aber jede von den 2b Möglichkeiten die Werte der i-ten Kolonne zu setzen liefert einen anderen Wert für h(y ) • Die Multiplikation h~x kann auch berechnet werden indem alle Kolonnen von h, für die die entsprechende Komponente in ~x 1 ist, modulo 2 addiert werden. • Daher ist die Wahrscheinlichkeit, dass h(x) = h(y ) gleich 1 2b = 1 N. • Im vorigen Beispiel werden also die Kolonnen 1 und 3 addiert. 4.37 Universelle Familie von Hashfunktionen 7 Suchalgorithmen 4.38 Outline Pierre Fierz Suchalgorithmen Pierre Fierz • Es gibt natürlich weitere universelle Familien von Hashfunktionen • Die folgende Konstruktion erinnert an die MAD-Methode. Ungeordnete Suchstruktur 1 Ungeordnete Suchstruktur Implementation als Hashtabelle Universelle Hashfunktion 2 • Die folgende Menge H von Hashfunktionen ist auch universell. Implementation als Hashtabelle Universelles Hashing Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array • wir definieren nun die folgende Familie von Funktionen: Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum • p sei eine Primzahl mit |U| ≤ p < 2|U| Ungeordnete Suchstruktur Implementation als 2-3-4-Baum 2 Geordnete Suchstruktur Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste ha,b (x) = ((ax + b) mod p)mod N • Die Menge H schliesslich ist folgendermassen definiert Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste und ist universell. H = {ha,b |0 < a < p ∧ 0 ≤ b < p} 4.39 4.40 Einführung Suchalgorithmen Java Spezifikation der sortierten Suchstruktur Pierre Fierz Suchalgorithmen Pierre Fierz Interface Assoziativer Array Ungeordnete Suchstruktur • Wir führen nun eine totale Ordnung auf die Menge der Schlüssel ein. • Dadurch erhalten wir die geordnete Suchstruktur. • Das bisherige Suchen wird um die folgenden Funktionalitäten erweitert. • Lesen aller Schlüssel in sortierter Reihenfolge. • Lesen aller Schlüssel ab einem gewünschten Schlüssels • Finden des kleinsten Schlüssels. Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Im folgenden ist das entsprechende Interface in Java angegeben. 1 public interface SortSuch<Key extends Comparable<Key>, Info> { 2 3 /** 4 * Suchen eines Elements mit Hilfe eines Keys. 5 * 6 * <pre> 7 * Precond: none 8 * Postcond: Falls das Element in der Suchstrucktur 9 new.found() == true * 10 new.readKey() == sk * 11 sonst * 12 new.found() == false * 13 * </pre> 14 * 15 * @param sk der gesuchte Key. 16 * @return true falls das Element in der Suchstruktur ist. 17 */ 18 public boolean search(Key sk); 19 20 /** 21 * Nächstes Element lesen. 22 * 23 * <pre> 24 * Precond: found() == true 25 * Postcond: Falls new.found() == true 26 new.readKey() > old.readKey() * 27 kein key zwischen new und old * 28 sonst * 29 old.readKey() ist groesster Key * 30 * </pre> 31 * 32 * @return true falls noch weitere Elemente vorhanden 33 * @throws BTE.NotFoundException 34 Falls keine Position existiert. * 35 */ 36 public boolean nextKey() throws BTE.NotFoundException; Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 4.41 Java Spezifikation der sortierten Suchstruktur 2 Suchalgorithmen 4.42 Java Spezifikation der sortierten Suchstruktur 3 Pierre Fierz Pierre Fierz Interface Assoziativer Array (Forts.) Interface Assoziativer Array (Forts.) Ungeordnete Suchstruktur 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 /** * Positionieren auf das kleinste Element * * <pre> * Precond: none * Postcond: Falls new.found() == true new.readKey() ist kleinster key * sonst * Keine Elemente in der Suchstruktur * * </pre> * * @return false falls die Struktur leer ist. */ public boolean reset(); Suchalgorithmen Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste /** * Gibt die Anzahl Elemente zurück. * * <pre> * Precond: none * Postcond: none * </pre> * * @return Anzahl Schluessel in der Struktur */ public int getKeyCount(); 4.43 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 /** * Testet ob ein Element positioniert ist. * * <pre> * Precond: none * Postcond: none * </pre> * * @return true falls ein key mit search(), nextKey() oder reset() gefunden wurde. * */ public boolean found(); /** * Einfügen eines neuen Elements mit * gegebenem Key. * * <pre> * Precond: search(key) == false * Postcond: new.search(key) == true new.found() == false * * </pre> * der Key des neuen Elements * @param key * @param data Nutzdaten des neuen Elements * @throws BTE.InTreeException Falls der Key schon im Baum ist. * */ public void insert(Key key, Info data) throws BTE.InTreeException; Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 4.44 Java Spezifikation der sortierten Suchstruktur 4 Suchalgorithmen Java Spezifikation der sortierten Suchstruktur 4 Pierre Fierz Suchalgorithmen Pierre Fierz Interface Assoziativer Array (Forts.) Interface Assoziativer Array (Forts.) 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 /** * Löschen eines Elementes mit gegebenem Key. * * <pre> * Precond: none * Postcond: new.search(key) == false new.found() == false * * </pre> * * @param key Der Key, der gelöscht werden soll. * @throws BTE.NotInTreeException Falls der Key nicht im Baum ist. * */ public void remove(Key key) throws BTE.NotInTreeException; 127 128 129 130 131 132 133 134 135 136 137 138 139 140 } Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Skipliste Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree /** * Lesen der Information zum aktuell positionierten * Element. * * <pre> * Precond: found() == true * Postcond: none * </pre> * * @return Object: Informationen zum aktuellen Element * @throws BTE.NotFoundException Falls keine Position existiert. */ public Info readInfo() throws BTE.NotFoundException; /** * Lesen des Keys zum aktuell positionierten Element. * * <pre> Precond: found() == true * Postcond: none * * </pre> * * * * @return Aktueller Key * @throws BTE.NotFoundException Falls keine Position existiert. * */ public Key readKey() throws BTE.NotFoundException; Implementation als Splay Baum • Wir wollen nun verschiedene Implementationen dieser Implementation als B-Tree Implementation als Skipliste Struktur besprechen. • Als sortierter Array • Als Baum unter anderem • • • • 2-3-4-Baum rot-schwarz-Baum splay-Tree B-Tree • Schliesslich noch als Skip-Liste 4.45 Implementation als sortierter Array Suchalgorithmen 4.46 Implementation als sortierter Array 2 Pierre Fierz Suchalgorithmen Pierre Fierz • Bei dieser Implementation werden die Schlüssel sortiert in einem Array a gespeichert • Die Variable anzahl gibt an, wieviele Elemente im Array gespeichert sind • Die Variable position dient zum sequentiellen lesen des Arrays. Operationen: Suchen: Binary Search. position wird auf das gefundene Element gesetzt. Next: Die Variable position wird um 1 erhöht. Reset: position wird auf 0 gesetzt. Einfügen: Der folgende Algorithmus fügt ein Element ein. Operationen (Forts.): Ungeordnete Suchstruktur Löschen: Der folgende Algorithmus löscht das Element an der Stelle position Implementation als Hashtabelle Universelles Hashing 1 { int i = position; 2 while (i < anzahl) { 3 such[i] = such[i+1]; 4 ++i; 5 } 6 --anzahl; 7 position = anzahl; 8 } Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum • Das Suchen hat die Komplexität O(log2 (anzahl)), Next Implementation als B-Tree Implementation als Skipliste und Reset haben Komplexität O(1) • Das Einfügen und das Löschen haben aber die 1 { int i = anzahl; 2 // Verschieben aller Elemente mit groesserem 3 // Schluessel als neu um eine Position nach oben. 4 while (i > 0 && such[i-1].key > neu.key) { 5 such[i] = such[i-1]; 6 --i; 7 } 8 //Das neue Element an der richtigen Stelle Einfuegen. 9 such[i] = neu; 10 ++anzahl; 11 position = anzahl; 12 } Komplexität O(anzahl) • Die Implementation als Array eignet sich sicher nur für eine kleine Anzahl von Elementen 4.47 4.48 Suchalgorithmen Implementation als binären Suchbaum Implementation als 2-3-4-Baum Pierre Fierz Suchalgorithmen Pierre Fierz • Der 2-3-4-Baum ist kein binärer Baum • Er wird uns aber helfen den Aufbau des • Wir können das geordnete Suchen als binären Suchbaum implementieren. Ungeordnete Suchstruktur rot-schwarz-Baumes besser zu verstehen. Implementation als Hashtabelle Implementation als Hashtabelle Definition (2-3-4-Baum) Universelles Hashing • Wie wir schon wissen, kann ein binärer Suchbaum im schlechtesten Fall zu einer linearen Liste entarten. • In diesem Fall ist die Komplexität einer Suchoperation im Geordnete Suchstruktur • Im Folgenden wollen wir zeigen, dass binäre Suchbäume so aufgebaut werden können, dass sie ausgeglichen bleiben. Universelles Hashing Geordnete Suchstruktur • Jeder Knoten enthält 1, 2 oder 3 Schlüssel in sortierter Implementation als sortierter Array Reihenfolge • Für innere Knoten gilt: Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Baum O(n) Ungeordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum • Ein 2-Knoten hat genau zwei Unterbäume. Links sind alle Implementation als Splay Baum Implementation als B-Tree kleineren rechts alle grösseren Schlüssel. • Ein 3-Knoten hat genau drei Unterbäume. Links sind alle kleineren rechts alle grösseren Schlüssel und in der Mitte alle Schlüssel, die zwischen den zwei Schlüsseln des Knotens liegen. • Ein 4-Knoten hat genau vier Unterbäume. Einen für jedes Intervall, dass durch die 3 Schlüssel definiert werden. Implementation als B-Tree Implementation als Skipliste • Das heisst, alle Wege von der Wurzel zu einem Blatt sind ungefähr gleich lang (O(log2 (n))). Implementation als Skipliste • Tiefen Eigenschaft: Alle Blätter des Baumes haben dieselbe Tiefe. 4.49 Suchalgorithmen Implementation als 2-3-4-Baum 2 4.50 Implementation als 2-3-4-Baum 3 Pierre Fierz Suchalgorithmen Pierre Fierz Beispiel: ein 2-3-4-Baum 50 70 • Operationen im 2-3-4-Baum. Ungeordnete Suchstruktur Implementation als Hashtabelle 10 30 33 55 58 62 100 Suchen: Man vergleicht mit allen Schlüsseln im Knoten. Falls der Schlüssel nicht im Knoten vorhanden, weiterfahren im entsprechenden Unterbaum. Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Theorem (Höhe des 2-3-4-Baumes) Die Tiefe eines 2-3-4-Baumes mit n Schlüsseln ist Θ(log2 (n)). Einfügen: Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum 1 2 Implementation als B-Tree Proof. Implementation als Skipliste • Auf der Tiefe i hat der Baum minimal 2i+1 − 1 Knoten ⇒ 2h+1 ≤ n + 1 • Auf der Tiefe i hat der Baum maximal 4i+1 − 1 Knoten 3 4 ⇒ n ≤ 4h+1 = 22(h+1) • Logarithmieren ergibt: Suche das Blatt, wo der Knoten eingefügt werden muss. Ist das Blatt ein 2- oder 3-Knoten, so kann der Schlüssel einfach eingefügt werden. Ist das Blatt ein 4-Knoten, so wird dieser in 2 2-Knoten aufgeteilt. Der mittlere Schlüssel wird in den Vorgängerknoten eingetragen Falls der Vorgängerknoten auch schon ein 4-Knoten ist, so wird rekursiv wie in 3 weitergefahren Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste h + 1 ≤ log2 (n + 1) ≤ 2h + 1 • daraus folgt sofort die Behauptung. 4.51 4.52 Suchalgorithmen Implementation als 2-3-4-Baum 3 Suchalgorithmen Implementation als 2-3-4-Baum 4 Pierre Fierz Pierre Fierz Löschen: Beim Löschen eines Schlüssels müssen wir nur den Fall betrachten, wo der Schlüssel in einem Blatt des Baumes liegt. Ungeordnete Suchstruktur Implementation als Hashtabelle Einfügen im 2-3-4-Baum Universelles Hashing 50 70 90 56 50 70 Geordnete Suchstruktur Wir nehmen an, dass der Schlüssel k in einem internen Knoten v an der Position i liegt: 1 Wir suchen im Unterbaum i des Knotens v das Blatt w, das am weitesten rechts liegt. (im Unterbaum immer dem Pointer ganz rechts verfolgen). 2 Wir Tauschen nun den grössten Schlüssel im Knoten w mit dem Schlüssel k im Knoten v. 3 Nun kann der Schlüssel k im Blatt w gelöscht werden. Implementation als sortierter Array 10 30 33 55 58 62 100 10 30 33 90 100 55 58 62 a) b) Implementation als Rot-Schwarz-Baum 58 50 58 70 Implementation als Splay Baum 35 55 56 62 Implementation als B-Tree 70 30 50 10 30 33 Implementation als 2-3-4-Baum Implementation als Skipliste 90 100 10 c) 33 35 55 56 62 90 100 d) Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 4.53 Implementation als 2-3-4-Baum 5 Suchalgorithmen 4.54 Suchalgorithmen Implementation als 2-3-4-Baum 6 Pierre Fierz Löschen: Beim Löschen eines Schlüssels in einem Blatt gibt es nun 3 Fälle: 1 Das Blatt besitzt mehr als einen Schlüssel. In diesem Fall kann der Schlüssel einfach aus dem Blatt entfernt werden. 2 Das Blatt enthält nur einen Schlüssel. In einem der Nachbarknoten sind aber mindestens 2 Schlüssel. In diesem Fall kann ein Schlüssel vom Nachbarknotenknoten ausgeliehen werden. 3 Das Blatt enthält nur einen Schlüssel. Beide Nachbarknoten besitzen auch nur einen Schlüssel. In diesem Fall wird der Knoten mit einem der Nachbarknoten zusammengelegt zusammen mit dem entsprechenden Schlüssel vom Vorgängerknoten. 4 Hat der Vorgängerknoten nur einen Schlüssel, so wird die Prozedur auf höherer Stufe rekursiv fortgesetzt. Pierre Fierz Löschen im 2-3-4-Baum Ungeordnete Suchstruktur 58 Ungeordnete Suchstruktur 58 Implementation als Hashtabelle Implementation als Hashtabelle Universelles Hashing 70 30 50 Universelles Hashing 70 33 50 10 Geordnete Suchstruktur Geordnete Suchstruktur 33 35 Implementation als sortierter Array 90 100 62 55 30 35 Implementation als 2-3-4-Baum 90 100 62 55 a) b) Implementation als 2-3-4-Baum 58 58 Implementation als sortierter Array Implementation als Rot-Schwarz-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum 70 33 50 55 Implementation als B-Tree Implementation als Skipliste Implementation als Splay Baum 70 33 30 Implementation als B-Tree 90 100 62 35 30 90 100 62 35 50 Implementation als Skipliste d) c) 58 33 58 70 33 90 30 30 62 35 50 e) 4.55 35 50 62 70 f) 4.56 Implementation als Rot-Schwarz-Baum Suchalgorithmen Suchalgorithmen Implementation als Rot-Schwarz-Baum 2 Pierre Fierz Pierre Fierz Darstellung von 2- und 3-Knoten im rot-schwarz-Baum Definition (rot-schwarz-Baum) • Der rot-schwarz-Baum ist ein binärer Suchbaum • Jeder Knoten hat entweder die Farbe rot oder schwarz • Zudem gelten die folgenden 3 Eigenschaften: 1 Wurzel Eigenschaft: Die Wurzel des Baumes ist immer schwarz. 2 Interne Eigenschaft: Die Kinder eines roten Knotens sind immer schwarz. 3 Tiefen Eigenschaft: Alle Blätter haben dieselbe schwarze Tiefe. Das heisst, auf jedem Weg von der Wurzel zu einem Blatt hat es gleich viele schwarze Knoten. 50 Ungeordnete Suchstruktur Ungeordnete Suchstruktur 20 50 100 20 100 Implementation als Hashtabelle Implementation als Hashtabelle Universelles Hashing Universelles Hashing Geordnete Suchstruktur 70 40 70 Geordnete Suchstruktur 40 oder Implementation als sortierter Array 40 Implementation als sortierter Array 70 Implementation als 2-3-4-Baum Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Rot-Schwarz-Baum 45 45 Implementation als Splay Baum Implementation als Splay Baum Implementation als B-Tree Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste Beispiel: Ein 2-3-4-Baum als rot-schwarz-Baum • Wir zeigen nun, wie 2-3-4-Bäume als schwarz-rot-Bäume dargestellt werden können und umgekehrt. 50 70 70 • Ein 2-Knoten ist ein schwarzer Knoten mit 2 schwarzen Kinder. 50 10 30 33 • Ein 3-Knoten besteht aus einem schwarzen Knoten mit 55 58 62 30 einem roten Kind. • Ein 4-Knoten besteht aus einem schwarzen Knoten mit zwei 10 roten Kinder. Implementation als Rot-Schwarz-Baum 3 100 100 58 33 55 62 4.57 Suchalgorithmen 4.58 Rot-Schwarz-Baum Suchen Pierre Fierz • Wir wollen die Tiefe des rot-schwarz-Baumes abschätzen. • Auf einem Weg von der Wurzel zu einem Blatt dürfen nie zwei rote Knoten hintereinander auftreten • Alle solche Wege haben gleich viele schwarze Knoten. • Der längste Weg ist ein solcher bei dem rote und schwarze Knoten immer alternieren. • Ein längster Weg ist also höchstens doppelt so lang wie ein kürzester Weg (nur schwarze Knoten). Suchalgorithmen Pierre Fierz Ungeordnete Suchstruktur Ungeordnete Suchstruktur Implementation als Hashtabelle • Der rot-schwarz-Baum ist unter anderem ein binärer Universelles Hashing Suchbaum. Geordnete Suchstruktur • Die Farbe der Knoten spielt aber beim Suchen keine Rolle Implementation als sortierter Array Implementation als 2-3-4-Baum • Suchen und traversieren eines rot-schwarz-Baumes Implementation als Rot-Schwarz-Baum Implementation als Splay Baum können also gleich implementiert werden wie im normalen Suchbaum. Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste • Die Tiefe des entsprechenden 2-3-4-Baumes entspricht • Die schwierigen Operationen sind also das Einfügen und aber genau der schwarzen Tiefe des rot-schwarz-Baumes. das Löschen. • Aus diesen Tatsachen kann man schliessen, dass die Höhe des Rot-Schwarz-Baumes O(log2 (N)) ist. 4.59 4.60 Suchalgorithmen Rot-Schwarz-Baum Einfügen Rot-Schwarz-Baum Einfügen 2 Pierre Fierz • Beim Einfügen verfahren wir vorerst wie beim Suchbaum 1 Suche den Schlüssel k bis ein leerer Pointer gefunden wird. 2 Füge den neuen Knoten ein. 3 Falls k die Wurzel ist, so färbe k schwarz sonst rot. • Durch diese Operation bleiben im Baum die Wurzel- und die Tiefen-Eigenschaft erhalten. • Falls der Vorgänger v des neuen Knoten k rot ist, dann ist die interne Eigenschaft verletzt. Wir nennen diesen Fall “doppel rot”. Suchalgorithmen Pierre Fierz Umstrukturierung Ungeordnete Suchstruktur • Der Bruder des Knotens v ist schwarz. Implementation als Hashtabelle • In diesem Fall bedeutet “doppel rot”, dass wir im Universelles Hashing Geordnete Suchstruktur entsprechenden 2-3-4-Baum einen neuen 4-Knoten kreiert haben. Implementation als sortierter Array Implementation als 2-3-4-Baum • Der Knoten ist aber im Rot-Schwarz-Baum falsch orientiert Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste ist. • Wir restrukturieren den Baum folgendermassen: 1 • Falls der Bruder von v schwarz ist, müssen wir eine Umstrukturierung vornehmen. 2 • Falls der Bruder von v rot ist, so genügt eine Umfärbung. 3 Nehme die Knoten k seinen Vater v und seinen Grossvater u und bennene diese als a, b und c so, dass diese der Grösse nach sortiert sind. nun ersetze den Grossvaterknoten u mit Knoten b und mache a und c zu den Kindern von b. Nun werden b als schwarz, a und c als rot markiert. Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 4.61 Suchalgorithmen Rot-Schwarz-Baum Einfügen 3 4.62 Rot-Schwarz-Baum Einfügen 4 Pierre Fierz Suchalgorithmen Pierre Fierz Umstrukturierung (Forts.) Falsch orientierte 4-Knoten im rot-schwarz-Baum u 90 v 70 k 20 u 90 20 v 20 u 20 70 v k 70 Ungeordnete Suchstruktur u 90 90 k v 70 k • Der Bruder w des Knotend v ist rot Universelles Hashing Geordnete Suchstruktur • In diesem Fall bedeutet “doppel rot”, dass im entsprechenden 2-3-4-Baum ein überlauf passiert ist (einfügen in einem 4-Knoten) • Wir färben nun die Knoten folgendermassen um: Implementation als sortierter Array Implementation als 2-3-4-Baum a) Implementation als Rot-Schwarz-Baum b Implementation als Splay Baum 70 a c 20 Umfärbung Implementation als Hashtabelle Implementation als B-Tree Implementation als Skipliste 90 1 2 3 b) 4 Die Knoten v und w werden schwarz gefärbt. Der Vorgänger u von v und w wird rot gefärbt. Ist der Vorgänger von u schwarz, so sind wir fertig. Ist der Vorgänger von u rot, so haben wir das “doppel rot” Problem eine Stufe höher und müssen das Problem mit einer Umfärbung oder einer Umstrukturierung dort lösen. Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Nach der Restrukturierung ist das “doppel rot” Problem gelöst • Alle drei Eigenschaften des rot-schwarz-Baumes sind wieder hergestellt. 4.63 4.64 Suchalgorithmen Rot-Schwarz-Baum Einfügen 5 Suchalgorithmen Rot-Schwarz-Baum Löschen Pierre Fierz Pierre Fierz Umfärbung (Forts.) • Als erstes stellen wir fest, dass der Schlüssel k immer in einem “Blatt” des entsprechenden 2-3-4-Baumes gelöscht werden kann (sonst austauschen wie üblich). Ungeordnete Suchstruktur Überlauf eines 4-Knoten im rot-schwarz-Baum Implementation als Hashtabelle • Falls der zu löschende Knoten rot ist, so kann er einfach Universelles Hashing 40 63 u 55 63 90 v 55 63 ... 63 u 90 w v 55 k 40 90 w 40 55 90 gelöscht werden. Geordnete Suchstruktur Implementation als 2-3-4-Baum k 40 Implementation als Splay Baum Implementation als B-Tree • Da eine Restrukturierung des Baumes das “doppel rot” • In diesem Fall kommt der Schlüssel des Nachfolgers in den schwarzen Knoten und der rote wird gelöscht. Implementation als Skipliste Problem löst, brauchen wir höchstens eine Restrukturierungsoperation. Universelles Hashing Implementation als sortierter Array Implementation als 2-3-4-Baum Nachfolger. Implementation als Rot-Schwarz-Baum Implementation als Hashtabelle Geordnete Suchstruktur • Ist der Knoten schwarz so hat er genau einen roten Implementation als sortierter Array Ungeordnete Suchstruktur Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Der einzige schwieriege Fall ist ein schwarzer Knoten ohne Nachfolger • Umfärbungen gibt es höchstens so viele wie die Hälfte der • Dies entspricht im 2-3-4-Baum dem Fall, dass der Knoten Höhe des Baumes das ist log2 (n). leer wird. • Das heisst, das Einfügen eines neuen Elementes im • Dieser Fall wird mit Hilfe einer Umstrukturierung oder Baum ist O(log2 (n)). Umfärbung gelöst. 4.65 Suchalgorithmen Rot-Schwarz-Baum Löschen 2 Pierre Fierz Fall 1: Umfärbung • Der Bruder z des Knotens k ist schwarz und hat keine roten Kinder der Vater r ist rot. • Dies entspricht im 2-3-4-Baum dem Fall wo wir die Knoten z und k verschmelzen. • Dies erreichen wir, indem z rot gefärbt und k gelöscht wird. Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum • Anschliessend wird der Vater r rot gefärbt Implementation als Rot-Schwarz-Baum Implementation als Splay Baum • Die Operation ist nun abgechlossen. Implementation als B-Tree Implementation als Skipliste Verschmelzen zweier Knoten u ... 30 40 u 30 • Der Bruder z des Knotens k ist schwarz und hat keine roten Kinder der Vater r ist schwarz. • Dies entspricht im 2-3-4-Baum dem Fall wo wir die Knoten z und k verschmelzen. • Wieder wird z rot gefärbt und k gelöscht. • Da der Vater r schwarz ist, so wird die Tiefen Eigenschaft des Rot-Schwarz-Baumes jetzt verletzt. • Der schwarze Weg zum Knoten z ist um 1 kürzer. Wir färben den Knoten r doppel schwarz um diese Tatsache darzustellen. • Im 2-3-4-Baum entspricht dies dem Fall, wo der Vaterknoten leer wird • Wir müssen das “doppel schwarz” Problem auf der höheren Ebene des Baumes lösen. 40 35 50 k Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 35 40 u ... 30 z Pierre Fierz Verschmelzen zweier Knoten r 40 50 Suchalgorithmen Rot-Schwarz-Baum Löschen 3 Fall 1: Umfärbung (Forts.) ... 30 30 r 35 4.66 u 30 ... 30 30 z 35 r r 40 40 40 z 35 4.67 50 k 35 50 z 35 35 40 4.68 Suchalgorithmen Rot-Schwarz-Baum Löschen 4 Fall 1: Umfärbung (Forts.) Pierre Fierz Fall2: Umstrukturierung • Wenn das “doppel schwarz” Problem auftritt, so müssen wir dieses auf der oberen Stufe lösen • Das Problem kann sich im schlechtesten Fall bis zur Wurzel des Baumes fortpflanzen. • Der Bruder v des “doppel schwarzen” Knoten r ist schwarz und hat ein rotes Kind. Ungeordnete Suchstruktur Schlüssels beim Nachbarknoten. Geordnete Suchstruktur 70 • Dabei werden die Knoten v , z der rote Sohn und u der Implementation als Rot-Schwarz-Baum 120 50 Implementation als Splay Baum 120 Implementation als B-Tree 30 10 58 33 55 90 62 80 150 100 125 30 200 10 58 33 55 90 62 Implementation als Skipliste 150 80 125 Vater von v Umstrukturiert. Implementation als Skipliste 200 ... 20 30 u 20 b 10 10 20 v 50 120 a 40 r 20 120 Implementation als Rot-Schwarz-Baum Implementation als B-Tree Umstrukturierung im rot-schwarz-Baum 70 50 Implementation als 2-3-4-Baum Implementation als Splay Baum ... 30 70 Geordnete Suchstruktur Implementation als sortierter Array Einfügen gelöst werden. Implementation als 2-3-4-Baum Implementation als Hashtabelle Universelles Hashing • Dieser Fall kann mit einer Umstrukturierung wie beim Implementation als sortierter Array 70 Ungeordnete Suchstruktur • Dieser Fall entspricht im 2-3-4-Baum dem Ausleihen eines Implementation als Hashtabelle Universelles Hashing Fortpflanzung von “doppel schwarz” 50 Suchalgorithmen Rot-Schwarz-Baum Löschen 5 Pierre Fierz 30 30 c 10 40 40 40 r 30 10 58 33 55 90 62 150 80 125 30 200 10 58 33 55 90 62 80 z 150 125 10 200 4.69 Suchalgorithmen Rot-Schwarz-Baum Löschen 6 Pierre Fierz Fall 2: Umstrukturierung (Forts.) • In der nächsten Abbildung ist der Fall dargestellt, wo der Ungeordnete Suchstruktur Implementation als Hashtabelle rote Sohn von v rot ist. Universelles Hashing Geordnete Suchstruktur Umstrukturierung im rot-schwarz-Baum Implementation als sortierter Array Implementation als 2-3-4-Baum ... 20 ... 30 30 u 20 b ... 10 ... 10 20 v 40 r 10 a 10 Implementation als Rot-Schwarz-Baum 30 Implementation als Splay Baum 30 c 40 40 Implementation als B-Tree Implementation als Skipliste z 40 r 20 4.70 Rot-Schwarz-Baum Löschen 7 Fall 3: Anpassung • Der Bruder v des “doppel schwarzen” Knoten r ist rot. z sei das linke Kind von v . • Wir führen wir eine Restrukturierung mit den Knoten z, v und u durch. v wird schwarz und u wird rot. • Wir haben nichts anderes getan, als den 3-Knoten (v , u) im 2-3-4-Baum im Rot-Schwar-baum anders darzustellen. • Nun liegt Fall 1 (Umfärbung) oder Fall 2 (Umstrukturierung) vor. • Da u rot ist kann es beim Fall 1 keine Fortpflanzung des “doppel schwarz” Problems mehr geben • Das heisst, pro Löschvorgang gibt es höchstens eine Anpassung. Suchalgorithmen Pierre Fierz Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Anpassung im rot-schwarz-Baum 20 30 • Die Umstrukturierung löst das “doppel schwarz” Problem u v 30 vollständig. ... 10 ... 20 ... 27 ... v 40 r 20 z 30 u 10 40 z 4.71 10 27 x 27 x r 40 4.72 Rot-Schwarz-Baum Löschen 8 Suchalgorithmen Implementation als Splay Baum Pierre Fierz Pierre Fierz Ungeordnete Suchstruktur • Da eine Umstrukturierung das “doppel schwarz” Problem löst, braucht es höchstens eine Umstrukturierung. • Wir haben gesehen, dass es höchstens eine Anpassung braucht. • Eventuell müssen wir log2 (n) Umfärbeoperationen durchführen. • Der Splay Baum unterscheidet sich wesentlich von den Implementation als Hashtabelle bisher besprochenen ausgelichenen Bäumen. Universelles Hashing Geordnete Suchstruktur • Ein Splay-Baum hat keine Regeln, um die Ausgeglichenheit des Baumes zu garantieren. Implementation als sortierter Array Implementation als 2-3-4-Baum • Um den Baum ausgeglichen zu halten (in einem Implementation als Rot-Schwarz-Baum Implementation als Splay Baum • Das heisst, das Löschen im Rot-Schwarz-Baum hat eine Komplexität von Suchalgorithmen Implementation als B-Tree Implementation als Skipliste amortisierten Sinne) wird nach jedem Zugriff eine sogenannte Splay-Operation ausgeführt. • Die Struktur des Splay-Baumes ist ein gewöhnlicher Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste binärer Suchbaum. O(log2 (n)) • Die amortisierten Kosten für das Suchen, Einfügen und . Löschen in einem Splay-Baum sind logarithmisch. 4.73 Implementation als Splay Baum 2 Suchalgorithmen 4.74 Implementation als Splay Baum 3 Pierre Fierz Suchalgorithmen Pierre Fierz zig-zig Operation: Ungeordnete Suchstruktur • Eine Splay-Operation bewegt einen Knoten x bis zur Wurzel des Baumes mit Hilfe einer Sequenz von restrukturierungs Operationen. • Die spezifischen Operationen, die ausgeführt werden, sind abhängig von: • Der Position vom Knoten x, • Der Position vom Vorgänger y von x und • falls dieser existiert, vom Vorgänger z von y Der Knoten x und sein Vorgänger sind beide linke oder beide rechte Nachfolger. Wir ersetzen z durch x, y wird nachfolger von x und z nachfolger von y . Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Die zig-zig Operation Implementation als 2-3-4-Baum Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als Splay Baum Implementation als B-Tree Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste • Nachfolgend sind die drei möglichen restrukturierungs Operationen angegeben. 4.75 4.76 Implementation als Splay Baum 4 Suchalgorithmen Implementation als Splay Baum 5 Pierre Fierz Suchalgorithmen Pierre Fierz zig Operation: zig-zag Operation: y ist ein rechter Nachfolger und x ein linker Nachfolger oder umgekehrt. Wir ersetzen z durch x. y und z werden zu den Nachfolgern von x. Die zig-zag Operation Ungeordnete Suchstruktur Falls der Vorgänger y von x die Wurzel des Baumes ist, so wird x zur neuen Wurzel des Baumes. Implementation als Hashtabelle Universelles Hashing Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Die zig Operation Geordnete Suchstruktur Geordnete Suchstruktur Implementation als sortierter Array Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als Splay Baum Implementation als B-Tree Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste 4.77 Implementation als Splay Baum 6 Suchalgorithmen 4.78 Implementation als Splay Baum 7 Pierre Fierz Suchalgorithmen Pierre Fierz Beispiel: Die Splay Operation Die Splay Operation: • Eine Splay-Operation auf einem Knoten x im Baum ist eine Folge von zig-zig, zig-zag und zig Operationen so, dass am Schluss der Knoten x zur neuen Wurzel des Baumes wird. • Bei jeder zig-zig oder zig-zag Operation nimmt die Tiefe des Knotens x um 2 ab. • Bei einer zig Operation nimmt die Tiefe des Knotens x um 1 ab. • Falls die Tiefe des Knotens x gleich d ist, so braucht eine Ungeordnete Suchstruktur Ungeordnete Suchstruktur Implementation als Hashtabelle Implementation als Hashtabelle Universelles Hashing Universelles Hashing Geordnete Suchstruktur Geordnete Suchstruktur Implementation als sortierter Array Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als Splay Baum Implementation als B-Tree Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste Splay-Operation d 2 zig-zig und/oder zig-zag Operationen. • Falls d ungerade ist, so braucht es noch die zig Operation • Die Splay Operation hat also Komplexität O(d) 4.79 4.80 Implementation als Splay Baum 7 Suchalgorithmen Suchalgorithmen Splay Baum amortisierte Kosten Pierre Fierz Pierre Fierz Anwendung der Splay Operation Suchen Falls der Schlüssel k im Knoten x gefunden wird, so wird die Splay-Operation auf den Knoten x ausgeführt. Falls die Suche erfolglos ist, so wird die Operation auf den Knoten ausgeführt, bei dem die Suche endet. Einfügen Wenn der Schlüssel k eingefügt wird, so wird die Splay-Operation auf den neu kreierten Knoten x ausgeführt. Löschen Beim Löschen des Schlüssels k wir die Splay-Operation entweder auf den Vorgänger des Knotens x der k enthält oder den Vorgänger eines Nachfolgers von x (der Knoten mit grösstem Schlüssel im linken Unterbaum von x) ausgeführt. Ungeordnete Suchstruktur Ungeordnete Suchstruktur Implementation als Hashtabelle Implementation als Hashtabelle • Wir haben schon festgestellt, dass der Splay-Baum sich Universelles Hashing Geordnete Suchstruktur im schlechtesten Fall nicht gut verhält (O(n)). Implementation als sortierter Array • Wir wollen zeigen, dass die amortisierten Kosten sich Implementation als 2-3-4-Baum logarithmisch verhalten. Implementation als Rot-Schwarz-Baum Implementation als Splay Baum • Die Kosten für das Suchen, Einfügen und Löschen sind proportional zu den Kosten einer Splay Operation. Implementation als B-Tree Implementation als Skipliste • Daher untersuchen wir die Kosten nur für die Splay Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Operation. 4.81 Splay Baum amortisierte Kosten 2 Suchalgorithmen 4.82 Suchalgorithmen Splay Baum amortisierte Kosten 3 Pierre Fierz Pierre Fierz • Wir definieren • T sei ein Splay-Baum mit n Knoten und x sei ein r (T ) = beliebiger Knoten. Wir definieren: s(x) = Anzahl Knoten im Unterbaum x r (x) = log2 (s(x)) • Wir bezahlen nun für eine zig-zig oder zig-zag Operation zwei Cyberdollars und für eine zig Operation einen Cyberdollar. • Mit diesem Schema kostet die Splay-Operation für einen Knoten x mit Tiefe d genau d Cyberdollars. • Wir wollen nun berechnen, wieviel wir pro Splay Operation bezahlen müssen, damit die folgende Invariante im Baum erhalten bleibt: Vor und nach einer Splay-Operation besitzt jeder Knoten x ∈ T r (x) Cyberdollar r (x) x∈T Ungeordnete Suchstruktur size : rang : X • um die Invariante nach einer Splay-Operation zu erhalten Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum müssen wir die Kosten der Operation plus die Änderung von r (T ) bezahlen. • Wir bezeichnen zig-zig, zig-zag und zig Operationen als Schritte der Splay-Operation. • Der Rang eines Knotens vor und nach einem Schritt bezeichnen wir mit r (x) beziehungsweise r 0 (x). Implementation als B-Tree Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste Theorem (Änderung von r (T )) Die Änderung δ von r (T ), die durch einen Schritt der Splay-Operation eines Knotens x ensteht, kann folgendermassen begrenzt werden: δ δ • Man beachte, dass diese Invariante gilt, wenn der Baum ≤ 3(r 0 (x) − r (x)) − 2 ≤ 3(r 0 (x) − r (x)) für zig-zig und zig-zag Schritte für einen zig Schritt leer ist. 4.83 4.84 Suchalgorithmen Splay Baum amortisierte Kosten 4 Splay Baum amortisierte Kosten 5 Pierre Fierz Pierre Fierz Proof. Wir beweisen den Satz nur für die zig-zig Operation (für die anderen siehe Skript). Dabei werden wir die folgende Tatsache (ohne Beweis) verwenden: Seien a > 0, b > 0 und c > a + b dann gilt: log(a) + log(b) ≤ log(c) − 2 (1) Theorem (Kosten einer Splay-Operation) T sei ein Splay-Baum mit Wurzel t und ∆ die Änderung von r (T ) bei einer Splay-Operation des Knotens x mit Tiefe d. Dann gilt: ∆ ≤ 3(r (t) − r (x)) − d + 2 Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Bei der zig-zig Operation ändert der Rang nur für die Knoten x, y und z. Es gilt: r 0 (x) r 0 (y ) r (x) = ≤ ≤ Geordnete Suchstruktur r (z) r 0 (x) r (y ) Implementation als sortierter Array δ = = ≤ Implementation als Splay Baum (2) Implementation als B-Tree Implementation als Skipliste Beachten Sie, dass s(x) + s0 (z) ≤ s0 (x) aus 1 folgt: r (x) + r 0 (z) r 0 (z) ≤ ≤ 2r 0 (x) − 2 2r 0 (x) − r (x) − 2 • • • • • ≤ = r 0 (x) + (2r 0 (x) − r (x) − 2) − 2r (x) 3(r 0 (x) − r (x)) − 2 Universelles Hashing Geordnete Suchstruktur Implementation als Rot-Schwarz-Baum Die Splay-Operation besteht aus p = d d2 e Schritte Falls d ungerade ist, so ist eine der Operationen eine zig Operation. Sei r0 (x) = r (x) und für i = 1..p sei ri der Rang von x nach dem i-ten Schritt. Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste δi sei die Änderung von r (T ) nach dem i-ten Schritt Nach dem vorherigen Theorem gilt: (3) ∆ aus 2 und 3 folgt nun die Behauptung δ Implementation als Hashtabelle Implementation als 2-3-4-Baum Proof. Implementation als Rot-Schwarz-Baum r 0 (x) + r 0 (y ) + r 0 (z) − r (x) − r (y ) − r (z) r 0 (y ) + r 0 (z) − r (x) − r (y ) r 0 (x) + r 0 (z) − 2r (x) Ungeordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Nun können wir δ abschätzen: Suchalgorithmen (4) = ≤ = ≤ Pp δi Pi=1 p (3(ri (x) − ri−1 (x)) − 2) + 2 i=1 3(rp (x) − r0 (x)) − 2p + 2 3(r (t) − r (x)) − d + 2 4.85 Splay Baum amortisierte Kosten 6 • Wir können nun die Resultate zusammenfassen: • Falls wir für eine Splay Operation 3(r (t) − r (x)) + 2 Cyberdollar bezahlen, dann können wir 1 2 d Cyberdollar für die Kosten der Operation bezahlen und 3(r (t) − r (x)) − d + 2 Cyberdollars bezahlen, so dass in jedem Knoten r (x) Cyberdollar gespeichert sind. • Der Baum T hat n Knoten also ist r (t) = log2 (n). Da r (x) ≤ r (t) folgt dass die Zahlung O(log2 (n) ist. Suchalgorithmen auch einer Such-, Einfüge- oder Löschoperation) Splay Baum amortisierte Kosten 7 Pierre Fierz Suchalgorithmen Pierre Fierz • Der Vorteil des Splay-Baumes ist, dass er adaptiv ist. • Schluessel auf die oft zugegriffen wird sind nahe bei der Wurzel Ungeordnete Suchstruktur Implementation als Hashtabelle Theorem Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum • Im Splay Baum sind die amortisierten Kosten einer Splay-Operation (also 4.86 Implementation als Splay Baum Wir betrachten wieder eine Sequenz von m Operationen, die mit einem leeren Splay-Baum beginnt. f (i) bezeichne die Anzahl Zugriffe auf das Element i und n sei die totale Anzahl der Elemente. Falls auf jedes Element im Baum zugegriffen wird, so ist der totale Aufwand gleich P O m + ni=1 f (i) log(m/f (i)) Implementation als B-Tree Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste • Das heisst, die amortisierte Zeit für einen Zugriff auf ein O(log(n)) Element i ist O(log(m/f (i))). Theorem (Amortisierte Kosten im Splay-Baum) Beispiel: Gleiches Element Für eine Sequenz von Operationen (suchen, einfügen oder löschen) der Länge m in einem leeren Splay-Baum ist der totale Aufwand gleich P O m+ m i=1 log(ni ) Als Beispiel nehmen wir an, dass für das Element i gilt f (i) = m/4. Dabei bezeichnet ni die Anzahl Knoten nach der i-ten Operation. Dies ist gleich O(m log(n)) wobei n = max1≤i≤m (ni ) In diesem Fall gilt O(log(m/(m/4))) = O(log(4)) = O(1). 4.87 4.88 Suchalgorithmen Implementation als B-Tree Implementation als B-Tree 2 Pierre Fierz Suchalgorithmen Pierre Fierz • Die folgende Definition für einen ausgeglichenen Baum wurden 1970 von R. Bayer und E. McCreigth aufgestellt. Ungeordnete Suchstruktur Implementation als Hashtabelle • Der B-Tree (Balanced Tree) kann als direkte Implementation als Hashtabelle Definition Universelles Hashing Verallgemeinerung des 2-3-4-Baumes gesehen werden • Er ist für das Suchen in grossen Datenmengen geeignet • Meistens wird er auf Sekundärspeicher implementiert • Daher werden pro Knoten möglichst viele Schlüssel gespeichert Ungeordnete Suchstruktur Geordnete Suchstruktur Universelles Hashing Ein B-Tree der Ordnung n (n ist eine Konstante des B-Trees) ist ein Baum mit folgenden Eigenschaften: Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum 1 Jeder Knoten des Baumes enthält höchstens 2 · n Elemente. 2 Jeder Knoten ausser der Wurzel enthält mindestens n Elemente. Dieses Kriterium garantiert, dass der Baum mindestens zu 50% gefüllt ist. Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste • Die meisten Datenbanken benutzen B-Trees um die Suche in den Daten zu beschleunigen. 3 Jeder Knoten ist entweder ein Blatt, d.h. hat keine Nachfolger, oder er hat m + 1 Nachfolger. m ist die Anzahl Schlüssel, die in diesem Knoten gespeichert ist. 4 Alle Blätter haben die gleiche Tiefe. Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 4.89 Suchalgorithmen Implementation als B-Tree 3 4.90 Implementation als B-Tree 4 Pierre Fierz Pierre Fierz Beispiel: B-Tree der Ordnung 2 mit 3 Stufen • Die Schlüssel im Array key sind sortiert abgelegt und es gilt: Ungeordnete Suchstruktur 52 1 Implementation als Hashtabelle Universelles Hashing 10, 20 2, 7, 8, 9 13, 16 70, 85 27, 33, 45 54, 63, 68 75, 78, 81 Suchalgorithmen 2 Geordnete Suchstruktur 88, 91, 97, 99 Implementation als sortierter Array Implementation als 2-3-4-Baum 3 Implementation als Rot-Schwarz-Baum • In Java könnte die Definition eines Knotens in etwa so aussehen. Implementation als Splay Baum Alle Schlüssel k im Baum mit k <key[0] sind im Unterbaum, der durch den Knoten p[0] definiert ist, gespeichert. Alle Schlüssel k im Baum mit k >key[m-1] sind im Unterbaum, der durch den Knoten p[m] definiert ist, gespeichert. Alle Schlüssel k im Baum mit key[i] < k < key[i+1] i = 0 . . . m-2 sind im Unterbaum, der durch den Knoten p[i+1] definiert ist, gespeichert. Implementation als B-Tree Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Implementation als Skipliste B-Tree Knoten Knoten eines B-Tree 1 2 3 4 5 6 public class Knoten { int m; Knoten Vorgaenger; Knoten p[(2 * ord) + 1]; Keys key[2 * ord]; }; p[0],key[0],p[1],key[1], p[2], key[2], . . . ,p[m−1], key[m−1],p[m] // // // // Anzahl Schluessel im Knoten Vorgaengerknoten Alle Nachfolger Schluessel sortiert u.s.w. Alle keys < key[0] Alle keys k mit key[0] < k < key[1] 4.91 4.92 Suchalgorithmen Implementation als B-Tree 5 Pierre Fierz Ungeordnete Suchstruktur Implementation als Hashtabelle • Die Operationen im B-Tree werden gleich implementiert wie im 2-3-4-Baum • Sie werden hier nur kurz besprochen (Details siehe Skript) Suchen 1 2 Universelles Hashing Geordnete Suchstruktur Implementation als B-Tree 6 Einfügen 1 Ein neuer Schlüssel wird immer in einem Blatt (sortiert) eingefügt. 2 Falls im Blatt kein Platz ist, wird ein neues Blatt kreiert. 3 Die 2n + 1 Schlüssel werden gleichmässig aufgeteilt und der mittlere Knoten in den Vorgänger eingefügt. Beispiel: Einfügen im B-Tree Implementation als sortierter Array Wird der Knoten nicht gefunden, so ist der Unterbaum gegeben wo weitergesucht wird. Pierre Fierz Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als 2-3-4-Baum 14 Implementation als Rot-Schwarz-Baum Im Knoten wird der Schlüssel mit Binarysearch gesucht. Suchalgorithmen 52 A Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als Splay Baum 10, 20 B Implementation als B-Tree Implementation als Skipliste 2, 7, 8, 9 70, 85 C 13, 14, 16 27, 33, 45 E F D 54, 63, 68 D 88, 91, 97, 99 H I 52 A 10, 20 B 2, 7, 8, 9 Implementation als Skipliste 75, 78, 81 G 96 Implementation als B-Tree 70, 85, 96 C 13, 14, 16 27, 33, 45 E F 54, 63, 68 75, 78, 81 G 88, 91 H I 97, 99 J 4.93 Implementation als B-Tree 7 Löschen 1 Schlüssel können immer in einem Blatt gelöscht werden. 2 Hat es in einem Knoten dann weniger als n Schlüssel, dann gibt es zwei Fälle: 1 2 Entlehnen von Schlüsseln bei einem Nachbarknoten, wenn dieser mehr als n-Schlüssel besitz. Verschmelzen von zwei Nachbarknoten (2n − 1) Schlüssel und entnehmen einen Knotens beim Vorgänger. Suchalgorithmen Pierre Fierz Beispiel: Löschen im B-Tree (verschmelzen) Ungeordnete Suchstruktur Implementation als Hashtabelle 52 Ungeordnete Suchstruktur Implementation als Hashtabelle 85 Universelles Hashing Universelles Hashing Geordnete Suchstruktur 10, 20 Geordnete Suchstruktur 70, 81 Implementation als sortierter Array Implementation als sortierter Array 2, 7, 8, 9 13, 16 27, 33, 45 Implementation als Rot-Schwarz-Baum 54, 63, 68 75, 78 52 85, 99 Zu wenig Elemente Implementation als Splay Baum 97 52 Suchalgorithmen Implementation als B-Tree 8 Pierre Fierz Implementation als 2-3-4-Baum Beispiel: Löschen im B-Tree (ausgleichen) 4.94 10, 20 Implementation als B-Tree 70 Implementation als Skipliste Implementation als Skipliste 70, 85 2, 7, 8, 9 2, 7, 8, 9 13, 16 Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree 10, 20 Implementation als 2-3-4-Baum 27, 33, 45 54, 63, 68 75, 78, 81 13, 16 27, 33, 45 54, 63, 68 75, 78, 81, 99 97, 99 10, 20, 52, 70 52 2, 7, 8, 9 10, 20 2, 7, 8, 9 13, 16 13, 16 27, 33, 45 54, 63, 68 75, 78, 81, 99 70, 81 27, 33, 45 54, 63, 68 75, 78 85, 99 4.95 4.96 Suchalgorithmen Implementation als Skipliste Suchalgorithmen Implementation als Skipliste 2 Pierre Fierz Pierre Fierz • Die Skipliste ist eine interessante Implementation des sortierten Suchens. • Die Skipliste hat keine Baumstruktur • Sie benutzt die Wahrscheinlichkeit um die Schlüssel zu organisieren • Nachfolgend ist eine Skipliste dargestellt. Ungeordnete Suchstruktur Implementation als Hashtabelle Implementation als Rot-Schwarz-Baum Implementation als B-Tree S4 − 17 S3 − 17 25 S2 − 17 25 31 S1 − 12 17 25 31 38 S0 − 12 17 25 31 38 + Implementation als Splay Baum Implementation als B-Tree + 50 + 55 + 55 + 8 8 44 55 Implementation als Skipliste 8 8 39 + 8 8 20 44 55 8 8 3 − 8 Implementation als Skipliste S5 8 Implementation als Splay Baum gilt: ∀k ∈ K : −∞< k < +∞ • Ferner gilt: 2 Implementation als 2-3-4-Baum Beispiel: Eine Skipliste • Jede Liste enthält die zwei Schlüssel −∞ und +∞ wobei 1 Implementation als sortierter Array Implementation als Rot-Schwarz-Baum 8 in aufsteigender Reihenfolge. Implementation als 2-3-4-Baum 8 • Jede Liste Si enthält eine Teilmenge der Schlüssel aus K Geordnete Suchstruktur • Auch bezeichnen wir h als die Höhe der Liste. Implementation als sortierter Array aus einer Menge von linearen Listen S = {S0 , S1 , . . . , Sh }. Universelles Hashing S1 , . . . , Sh darüber zu zeichnen. Geordnete Suchstruktur • Eine Skipliste für eine Menge von Schlüsseln K besteht Implementation als Hashtabelle • Es ist üblich die Liste S0 zuunterst und die Listen Universelles Hashing Definition (Skipliste) Ungeordnete Suchstruktur Die Liste S0 enthält alle Schlüssel aus K . Für i = 1, 2, . . . , h − 1 enthält die Liste Si eine zufällig generierte Teilmenge der Schlüssel aus der Liste Si−1 . Die Liste Sh enthält nur die Elemente −∞ und +∞. 4.97 Suchalgorithmen Implementation als Skipliste 3 4.98 Implementation als Skipliste 4 Pierre Fierz • Die Schlüssel in der Liste Si+1 werden zufällig aus der Liste Si ausgewählt. Si+1 ist, beträgt 21 . Ungeordnete Suchstruktur • Wir können die Skipliste als zweidimensionale Struktur Implementation als Hashtabelle von Positionen ansehen • Diese sind horizontal in Ebenen und vertikal in Türme Geordnete Suchstruktur angeordnet. • Durch diese Positionen können wir nun mit den vier folgenden Operationen navigieren: Implementation als sortierter Array • So erwarten wir, dass S1 etwa allgemeinen Si etwa Pierre Fierz Universelles Hashing • Die Wahrscheinlichkeit, dass ein Schlüssel in Si auch in n 2i n 2, S2 etwa Schlüssel enthält. n 4 und im • Wir erwarten also, dass die Höhe h etwa log2 (n) sein wird. • Die Halbierung der Elemente von einer Liste zur anderen Suchalgorithmen Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste wird nicht als Eigenschaft der Skipliste gefordert. • Die Eigenschaft wird nur mit Hilfe von Randomisierung in etwa erzielt. 4.99 after(p) Gibt Position nach p in derselben Ebene zurück. before(p) Gibt Position vor p in derselben Ebene zurück. below(p) Gibt Position unterhalb p im selben Turm zurück. above(p) Gibt Position oberhalb p im selben Turm zurück. • Falls eine gesuchte Position nicht existiert, geben die Funktionen null zurück. Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 4.100 Implementation als Skipliste: Suchen • Der folgende Algorithmus findet den grössten Schlüssel der kleiner oder gleich k ist. Suchen in der Skipliste 1 2 3 4 5 6 7 8 9 10 11 12 Suchalgorithmen Pierre Fierz 1 Implementation als Hashtabelle 2 Universelles Hashing 6 7 Implementation als 2-3-4-Baum 8 Implementation als Rot-Schwarz-Baum 9 Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste 17 S3 − 17 Implementation als Skipliste − S4 − 17 S3 − 17 25 S2 − 17 25 31 25 31 38 25 31 38 + 8 + 25 31 38 8 20 39 44 50 55 + S0 − 12 17 55 + 20 39 + 55 + 55 + 42 44 42 44 50 8 17 17 8 12 44 12 + 55 8 38 − 55 42 8 31 S1 8 25 + 8 17 8 12 55 42 8 31 8 25 + 8 55 8 8 S5 8 25 8 − Implementation als B-Tree } 8 S0 Implementation als Splay Baum + 17 8 − 13 Implementation als Rot-Schwarz-Baum 8 8 S1 12 Implementation als 2-3-4-Baum + 8 − 11 Implementation als sortierter Array Beispiel: Einfügen des Schlüssels 42 8 S2 10 Geordnete Suchstruktur 8 − Universelles Hashing p = skipSearch(k); insertAfter(p, k); while (random() < 1/2) { while (above(p) == null) { p = before(p); } p = above(p); insertAfter(p, k); } 5 Implementation als sortierter Array Implementation als Hashtabelle 3 8 − S4 Pierre Fierz Ungeordnete Suchstruktur public void skipInsert(k) { SkipPosition p; 4 Geordnete Suchstruktur Beispiel: Suchen des Schlüssels 50 S5 Suchalgorithmen Einfügen in der Skipliste Ungeordnete Suchstruktur public SkipPosition skipSearch(k) { SkipPosition p; // p ist erstes Element der obersten Liste p = topLeft; while (below(p) != null) { p = below(p); while(after(p).key() <= k) { p = after(p); } } return p; } Implementation als Skipliste: Einfügen • Der folgende Algorithmus fügt den Schlüssel k ein. 4.101 Implementation als Skipliste: Löschen • Der folgende Algorithmus löscht den Schlüssel k . Suchalgorithmen 2 3 Universelles Hashing p = skipSearch(k); if (p.key() != k) { throw new KeyNotFoundException(); } while (p != null) { removeAfter(before(p)); p = above(p); } 4 5 6 7 8 9 10 11 12 vergrössert Implementation als Hashtabelle Geordnete Suchstruktur Implementation als sortierter Array • Wie hoch darf eine Skipliste maximal werden? • Es gibt dafür zwei mögliche Lösungen. 1 Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree } Implementation als Skipliste 2 Beispiel: Löschen des Schlüssels 25 S5 − S4 − 17 S3 − 17 25 S2 − 17 25 31 S1 − 12 17 25 31 38 S0 − 12 17 25 31 38 8 8 + 8 8 + + 55 + Universelles Hashing Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste eine vernünftige Wahl ist. Die andere Möglichkeit ist, wie im gegebenen Algorithmus, die Höhe wachsen zu lassen, solange random < 1/2 erfüllt ist. Wir werden in der Analyse des Algorithmus sehen, dass die Wahrscheinlichkeit, dass die Höhe grösser wird als O(log2 (n)) sehr klein ist. 8 8 50 Implementation als Hashtabelle 8 8 44 + 55 Wir beschränken die maximale Höhe der Liste auf einen fixen Wert, der davon abhängig ist, wieviele Elemente in der Liste sind. Wir werden bei der Analyse sehen, dass der Wert h = max(10, 3 · dlog2 (n)e) Ungeordnete Suchstruktur 8 8 39 + 55 8 8 20 44 55 Suchalgorithmen Pierre Fierz • Beim Einfügen, wird die Höhe der Skipliste evtl. Ungeordnete Suchstruktur public void skipRemove(k) { SkipPosition p; Implementation als Skipliste: Höhe der Liste Pierre Fierz Löschen in der Skipliste 1 4.102 4.103 4.104 Suchalgorithmen Skipliste: Komplexitätsanalyse Skipliste: Komplexitätsanalyse 2 Pierre Fierz • Als erstes wollen wir den Erwartungswert für die Höhe h der Liste S • Die Wahrscheinlichkeit, dass ein gegebener Schlüssel in der Ebene i gespeichert ist, ist 1 2i • Daher ist die Wahrscheinlichkeit Pi , dass überhaupt ein Schlüssel in der • Die äussere Schlaufe geht von h nach 0 Universelles Hashing Geordnete Suchstruktur Pi ≤ • Die innere Schleife auf der Ebene i bricht ab, sobald wir Implementation als Splay Baum • Das heisst, h ist höher als 3 log2 (n) mit einer Wahrscheinlichkeit von höchstens n 23 log2 (n) einen Schlüssel finden der auch in der Ebene i + 1 ist. Implementation als Rot-Schwarz-Baum n 2i = Implementation als B-Tree Implementation als Skipliste 1 n = 2 n3 n Suchalgorithmen Pierre Fierz • Ähnlich wie für das Suchen kann man zeigen, dass der Ungeordnete Suchstruktur Implementation als Hashtabelle Universelles Hashing • Wie wir oben schon festgestellt haben, ist der Erwartungswert der Anzahl Schlüssel auf der Ebene i gleich 2ni • Daraus können wir den Erwartungswert für die gesammte Geordnete Suchstruktur Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Anzahl gespeicherter Schlüssel in S berechnen und die ist: h h X X n 1 = n < 2n 2i 2i i=0 Implementation als sortierter Array Implementation als 2-3-4-Baum Implementation als Rot-Schwarz-Baum Implementation als Splay Baum Implementation als B-Tree Implementation als Skipliste Komplexität der Suche in einer Skipliste = O(log2 (n)) 4.105 für die Skipliste nicht zu gross ist. Universelles Hashing Geordnete Suchstruktur • Zusammengefasst: 1 f ür c > 1 nc−1 • Also ist die Höhe h einer Skipliste mit hoher Wahrscheinlichkeit O(log2 (n)). • Wir wollen am Schluss noch zeigen, dass der Platzbedarf Ebene i gespeichert ist auch in der Ebene i + 1 gespeichert ist, ist ja 1/2. Implementation als Hashtabelle Vorwärtsschritte auf der Ebene i ist 2, also O(1). Pc log2 (n) = Erwartungswert für die Anzahl Operationen beim Einfügen und beim Löschen eines Schlüssels auch O(log2 (n)) ist. • Die Wahrscheinlichkeit, dass ein Schlüssel der in der Ungeordnete Suchstruktur • Das heisst, der Erwartungswert der Anzahl • Allgemein: Skipliste: Komplexitätsanalyse 3 • Da h mit hoher Wahrscheinlichkeit O(log2 (n) ist, wird diese Schlaufe O(log2 (n)) mal durchlaufen. Implementation als sortierter Array Implementation als 2-3-4-Baum Ebene i gespeichert ist, gleich P3 log2 (n) ≤ Schlaufen. Ungeordnete Suchstruktur Implementation als Hashtabelle Höhe nicht beschränkt wird. Pierre Fierz • Beim Suchen haben wir zwei ineinander geschachtelte bestimmen • Wir nehmen an, dass beim Einfügen eines Elementes in der Skipliste die Suchalgorithmen i=0 • Der erwartete Platzbedarf für die Skipliste S ist O(n) 4.107 4.106