Kapitel 9 Suchalgorithmen Technische Universität München Suchverfahren: Verfahren, das in einem Suchraum nach Mustern oder Objekten mit bestimmten Eigenschaften sucht. Vielfältige Anwendungsbereiche für Suchverfahren: u.a. Suchen in Datenbanken, Google-Search, DNA-Tests Suchen nach ähnlichen Mustern: z.b. Viren, Malware Bilderkennungsverfahren: Suchen nach Pattern Ziel: einfache Suchverfahren auf Listen und Bäumen Basis: Elementare Datenstrukturen Effiziente Datenstrukturen: Bäume, Listen und Hashtabellen AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 1
Im Folgenden: Suchalgorithmen angepasst an die Anforderungen: 1. Statische, kleine Menge, selten Suchoperation notwendig: Lösung: Feld als Datenstruktur und sequentielles Suchen: O(n) 2. Statische, kleine Menge, häufige Zugriffe/Suchoperationen Lösung: Vorsortiertes O(n log n) Feld, binäres Suchen O(log n) 3. Dynamisch, große Menge von Elementen, z.b. Personaldaten Lösung: Baum als dynamische Datenstruktur (einfügen, löschen), organisiert als binärer Suchbaum O(h), h ist Baumhöhe Worst-Case: h = n, Best-Case: h= log n (balanciert) 4. Dynamisch, große Menge, viele, effiziente Zugriffe notwendig z.b. große Produktdatenbanken, Suchmaschinen, Lösung: Binärer Suchbaum, der eine möglichst geringe Höhe h garantiert: z.b. Rot-Schwarz Baum AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 2
Suchalgorithmen analog zum Sortieren: Charakterisierung der gesuchten Objekte durch Such-Schlüssel. Such-Schlüssel können z.b. Attribute der Objekte sein. Beispiel: Versicherungsnummer von Personen 9.1 Lineare Suche Gegeben sei ein Feld A[1.. n] von (ggf. auch unsortierten) Datenelementen und ein Element x mit Such-Schlüssel k. Idee der linearen Suche: sequentielles Durchlaufen des Feldes A und Vergleich der Schlüssel A[i], i=1,, n, mit dem Such-Schlüssel k. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 3
Laufzeitanalyse: Best-Case: sofortiger Treffer: T(n) = 1, also T(n) = O(1) Worst-Case: alles durchsuchen: T(n) = n, also T(n) = O(n) Average-Case: erfolgreiche Suche unter der Annahme, dass jede Anordnung der Elemente gleich wahrscheinlich ist: T(n) = also T(n) = O(n) Fazit: sehr einfaches Verfahren, eignet sich auch für einfach verkettete Listen, das Verfahren ist auch für unsortierte Felder geeignet, aber das Verfahren ist nur für kleine Werte von n praktikabel. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 4
9.2 Binäre Suche Falls in einer Folge häufig gesucht werden muss, so lohnt es sich, die Feldelemente sortiert zu speichern. Vorgehen: Eingabe: Sortiertes Feld halbieren des Suchbereichs in jedem Schritt, indem der gesuchte Wert mit dem Wert auf der Mittelposition des geordneten Feldes verglichen wird. Gesuchter Wert ist kleiner: weiterarbeiten mit linkem Teilfeld. Gesuchter Wert ist größer: weiterarbeiten mit rechtem Teilfeld. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 5
Eingabe: Feld A[1.. n], Schlüssel s Ausgabe: Position von s oder 0, falls s nicht vorhanden BINARY-SEARCH(A, s) 1 l = 1 2 r = n 3 while (s A[m] und l r) 4 m = (l + r) / 2 5 if s < A[m] 6 r = m 1 7 else l = m + 1 8 if s == A[m] 9 return m 10 else return 0 Beispiel: Eingabe: Sortiertes Feld A = (5, 15, 20, 22, 37) AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 6
Binary Search Algorithm C Code int BinarySearch(int *array, int key, int low, int high) { int middle; if(low > high) /* termination case */ return -1; middle = (low+high)/2; if(array[middle] == key) return middle; else if(array[middle] > key) return BinarySearch(array, key, low, middle-1); /* search left */ return BinarySearch(array, key, middle+1, high); /* search right */ } AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 7
Binary Search Algorithm C Code #include <stdbool.h> typedef unsigned long ulong; typedef int (*CompareProc) /* compares an element key against the desired key */ ( ulong Element, void * Arg ); /* result should be -1, 0 or +1, indicating whether given key is less than, equal to or greater than desired key. */ bool Search ( ulong LowBound, ulong HighBound, CompareProc Compare, void * CompareArg, bool ReturnGreater, ulong * Location ) AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 8
Binary Search Algorithm C Code { ulong MidElement; bool Found; int Comparison; for (;;) { if (LowBound > HighBound) { Found = false; if (ReturnGreater) { *Location = LowBound; } else { *Location = HighBound; } /*if*/ break; } /*if*/ MidElement = (LowBound + HighBound) / 2; Comparison = Compare(MidElement, CompareArg); if (Comparison < 0) { LowBound = MidElement + 1; } else if (Comparison > 0) { HighBound = MidElement - 1; } else { *Location = MidElement; Found = true; break; } /*if*/ } /*for*/ return Found; } /*Search*/ AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 9
Laufzeitanalyse: Zählen der Anzahl der Vergleiche Best-Case: sofortiger Treffer: T(n) = 1, also T(n) = O(1) Worst-Case: Suchbereich muss solange halbiert werden, bis er nur noch 1 Element enthält, also im schlechtesten Fall logarithmisch oft : T(n) = T(n/2) 1 = log(n + 1), T(n) = (log n) AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 10
Laufzeitanalyse: Zählen der Anzahl der Vergleiche Average-Case: es gilt T(n) = = Θ(log n) AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 11
Fazit: Binäre Suche gut geeignet für große Werte n Beispiel: sei n = 2 Millionen Lineare Suche benötigt im Worst Case 2 Millionen Vergleiche Binäre Suche benötigt: log (2 * 10 6 ) 20 Vergleiche nicht gut geeignet, wenn sich die Daten häufig ändern, dann ist das Suchen in binären Suchbäumen (s.u.) besser geeignet. 9.3 Suchen in binären Suchbäumen Kapitel 7: Entscheidungsbaum für Sortieren ist auch ein Suchbaum Binärer Suchbaum: Datenstruktur, um in einer dynamisch sich ändernden Menge von Daten zu suchen AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 12
Repräsentation eines binären Suchbaumes: als eine verkettete Liste. Jeder Knoten des Baumes besitzt mindestens die Attribute: Suchschlüssel, links, rechts, p, das sind Verweise auf das linke und rechte Kind, sowie auf den Vaterknoten (vgl. Kapitel 7) AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 13
Suchbaum-Eigenschaft Der Baum ist so organisiert, dass die Suchbaum-Eigenschaft gilt: sei x ein Knoten und y ein Knoten im linken Unterbaum von x, dann gilt: schlüssel[y] schlüssel[x]. Ist y ein Knoten im rechten Unterbaum von x, so gilt: schlüssel[x] schlüssel[y]. Eigenschaften binärer Suchbäume Operationen auf dem Baum, wie Suchen, Einfügen, Entnehmen, sind in O(h) Schritten ausführbar, wobei h die Höhe des Baumes ist. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 14
Binärer Suchbäume Bem.: Unterschiedliche binäre Suchbäume können die gleiche Menge von Werten repräsentieren. Beispiel: Eingabe: Werte 2, 3, 5, 7, 8 Fall (a) Suchbaum mit 6 Knoten der Höhe h = 2 Fall (b) Suchbaum mit gleichen Schlüssel, der weniger effizient organisiert ist und die Höhe h = 4 besitzt. Fall (a) Fall (b) AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 15
9.3.1 Suchen in binären Suchbäumen Aufgabe: Suche nach einem Schlüssel k in dem Baum. Rekursive Beschreibung der Suche: durch Rekursion wird ein Pfad von der Wurzel zum gesuchten Knoten beschrieben, d.h. Laufzeit von Tree-Search ist O(h), h ist die Baumhöhe. TREE-SEARCH(x, k) 1 if x == NULL oder k == schlüssel[x] 2 return x 3 if k < schlüssel[x] 4 return TREE-SEARCH(links[x], k) 5 else return TREE SEARCH(rechts[x], k) Beispiel: Suche nach k=13 AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 16
Häufig ist eine rekursiv programmierte Suche auf Rechnern nicht so effizient ausführbar wie eine iterativ programmierte Suche. Iterative Beschreibung der Suche: ITERATIVE-TREE-SEARCH(x, k) 1 while x NULL und k schlüssel[x] 2 if k < schlüssel[x] 3 x = links[x] 4 else x = rechts[x] 5 return x AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 17
9.3.2 Minimum und Maximum Suche Eine häufig benötigte Operation ist die Suche nach dem kleinsten bzw. größten Element des Baumes. Suche nach kleinstem Element: ist wegen der binären Suchbaum-Eigenschaft sehr einfach: gehe von der Wurzel immer den linken Teilbaum hinunter: Tree-Minimum gibt einen Zeiger auf das Element x mit dem kleinsten Schlüssel zurück. Terminierung, wenn der linke Teilbaum eines Knotens x NULL ist TREE-MINIMUM (x) 1 while links[x] NULL 2 x = links[x] 3 return x Beispiel-Baum auf Folie 14: minimales Element: x = 2 AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 18
Suche nach größtem Element: analoges Vorgehen gehe von der Wurzel immer den rechten Teilbaum hinunter: Tree-Maximum gibt einen Zeiger auf das Element x mit dem größten Schlüssel zurück. Terminierung, wenn der rechte Teilbaum eines Knotens x NULL ist Beispiel-Baum auf Folie 14: maximales Element: x = 20 Laufzeit: TREE-MAXIMUM(x) 1 while rechts[x] NULL 2 x = rechts[x] 3 return x Tree-Minimum und Tree-Maximum benötigen für einen Baum mit Höhe h eine Laufzeit von O(h); Berechnung baut einen Pfad von der Wurzel bis zum Blatt entlang linker bzw. rechter Äste auf. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 19
9.3.3 Nachfolgerknoten eines Knotens x Seien die Schlüssel der Knoten paarweise verschieden, dann gilt: Nachfolger von x ist der Knoten y mit: schlüssel[x] < schlüssel[y] und für alle Knoten r y, mit schlüssel[x] < schlüssel[r] gilt: schlüssel[y] < schlüssel[r] TREE-SUCCESSOR(x) 1 if rechts[x] NIL 2 return TREE-MINIMUM(rechts[x]) 3 y = p[x] 4 while y NIL und x == rechts[y] 5 x = y 6 y = p[y] 7 return y AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 20
9.3.4 Einfügen und Löschen in binärem Suchbaum Ziel: Aufrechterhalten der binären Suchbaum-Eigenschaft! Einfügen Einzufügen sei ein Knoten z, mit schlüssel[z] = v, links[z] = NULL, rechts[z] = NULL Finden der korrekten Position TREE-INSERT(T, z) 1 y = NULL 2 x = wurzel[t] 3 while x NULL 4 y = x 5 if schlüssel[z] < schlüssel[x] 6 x = links[x] 7 else x = rechts[x] 8 p[z] = y 9 if y == NULL 10 wurzel[t] = z 11 else if schlüssel [z] < schlüssel[y] 12 links[y] = z 13 else rechts[y] = z AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 21
Beispiel: Einfügen eines Knotens z mit schlüssel[z] = 13 Hell schattierte Knoten in Abb.: Pfad von der Wurzel bis zur korrekten Position Gestrichelte Linie: neue Verbindung, um das Element z einzufügen Tree-Insert startet bei der Wurzel: Zeiger x verfolgt den Pfad, Zeiger y verweist auf den Vater von x, In der while-schleife wandern beide Zeiger im Baum nach unten. Wenn x auf NULL verweist: Position für das Einfügen ist gefunden. Anweisungen in den Zeilen 8-13 fügen Knoten z ein. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 22
Einfügen ist somit auch eine einfache Operation auf Suchbäumen. Die Laufzeit von Tree-Insert ist ebenfalls O(h), h ist die Baumhöhe. Löschen Vgl. nächste Folie, dort ist das Vorgehen veranschaulicht. TREE-SUCCESSOR(x) 1 if rechts[x] NIL 2 return TREE-MINIMUM(rechts[x]) 3 y = p[x] 4 while y NIL und x == rechts[y] 5 x = y 6 y = p[y] 7 return y TREE-DELETE(T, z) 1 if links[z] == NULL or rechts[z] == NULL 2 y = z 3 else y = TREE-SUCCESSOR(z) 4 if links[y] NULL 5 x = links[y] 6 else x = rechts[y] 7 if x NULL 8 p[x] = p[y] 9 if p[y] == NULL 10 wurzel[t] = x 11 else if y = links[p[y]] 12 links[p[y]] = x 13 rechts[p[y]] = x 14 if y z 15 schlüssel[z] = schlüssel[y] 16 kopiere die Daten von y in z 17 return y AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 23
Beispiel: die drei Fälle des Tree-Delete Fall (a) z hat keine Kinder Fall (b) z hat nur ein Kind Fall (c) z hat 2 Kinder AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 24
Bem.: Die Operationen auf binären Suchbäumen haben alle eine Laufzeit, die proportional zu Höhe des Baumes ist. Binäre Suchbäume können aber degeneriert sein, d.h. bei einem Baum mit n Knoten kann im Worst-Case die Laufzeit (n) sein Ziel: Strukturieren von Suchbäumen so, dass Höhe h für gute Performance sorgt! Lösung: Konstruktion von balancierten Suchbäumen, so dass gilt: Der Baum hat eine garantierte kleine Höhe und die Laufzeit ist O(lg n). B-Bäume, AVL-, oder Rot-Schwarz-Bäume sind hierfür geeignet AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 25
9.4 Rot-Schwarz-Baum (R. Bayer, 1972) Ein Rot-Schwarz-Baum ist ein Binärer Suchbaum, der näherungsweise balanciert ist. Die Knoten des Baumes besitzen ein zusätzliches Attribut: farbe Das Attribut farbe kann zwei Werte annehmen: rot und schwarz Ein Rot-Schwarz-Baum erfüllt die Rot-Schwarz-Eigenschaft: Jeder Knoten ist entweder rot oder schwarz. Die Wurzel ist schwarz und jedes Blatt ist schwarz. Wenn ein Knoten rot ist, dann sind seine beiden Kinder schwarz. Für jeden Knoten x enthalten alle Pfade mit der Wurzel x und die in einem Blatt des Teilbaums von x enden, die gleiche Anzahl schwarzer Knoten. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 26
Rot-Schwarz-Eigenschaft (Wiederholung) 1. Jeder Knoten ist entweder rot oder schwarz. 2. Die Wurzel ist schwarz und jedes Blatt ist schwarz. 3. Wenn ein Knoten rot ist, dann sind seine beiden Kinder schwarz. 4. Für jeden Knoten x enthalten alle Pfade mit der Wurzel x und die in einem Blatt des Teilbaums von x enden, die gleiche Anzahl schwarzer Knoten. Beispiel: AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 27
Beispiel für einen Rot-Schwarz-Baum (siehe Cormen) Bei der Darstellung werden aber idr die NIL-Blätter ignoriert und nur die inneren Knoten betrachtet: AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 28
Operationen auf Rot-Schwarz-Bäumen AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 29
9.4.1 Einfügen auf Rot-Schwarz-Bäumen Zentrale Operation: Rotation, um r/s Eigenschaft zu garantieren Fall 1 AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 30
Einfügen auf Rot-Schwarz-Bäumen (Forts.) Fall 2 Fall 3 AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 31
Rotationen Verändern der Zeigerstrukturen Rotation: lokale Operation auf einem Suchbaum, die die binäre Suchbaumeigenschaft beibehält Linksrotation auf einem Knoten x: Voraussetzung: rechtes Kind y ist nicht NIL dreht die Verbindung zwischen x und y um y wird neue Wurzel und x das linke Kind von y das vor der Rotation linke Kind von y wird das rechte Kind von x Rechtsrotation analog Aufwand: O(1) AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 32
Rotationen LEFT-ROTATE(T, x) 1 y = rechts[x] // Setze y 2 rechts[x] = links[x] // Wandle y s linken Teilbaum in x s rechten Teilbaum 3 if links[y] NIL 4 p[links[y]] = x 5 p[y] = p[x] // Verbinde den Vater von x mit y 6 if p[x] = NIL 7 wurzel[t] = y 8 else if x == links[p[x]] 9 links[p[x]] = y 10 else rechts[p[x]] = y 11 links[y] = x // Verschiebe x auf 12 p[x] = y // die linke Seite von y AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 33
Einfügen in Rot/Schwarz-Baum Variante der Tree-Insert-Operation, O(lg n) Anschließend wird neuer Knoten rot gefärbt Sicherstellen der r/s-eigenschaft: Aufruf von RB-Insert-Fixup: Knoten werden neu gefärbt und Rotationen durchgeführt RB-INSERT(T, z) 1 y = NIL 2 x = wurzel[t] 3 while x NIL 4 y = x 5 if schlüssel[z] < schlüssel[x] 6 x = links[x] 7 else x = rechts[x] 8 p[z] = y 9 if y == NIL 10 wurzel[t] = z 11 else if schlüssel[z] < schlüssel[y] 12 links[y] = z 13 else rechts[y] = z 14 links[z] = NIL 15 rechts[z] = NIL 16 farbe[z] = ROT 17 RB-INSERT-FIXUP(T, z) RB-INSERT-FIXUP(T, z) 1 while farbe[p[z]] == ROT 2 if p[z] == links[p[p[z]]] 3 y = rechts[p[p[z]]] 4 if farbe[y] == ROT 5 farbe[p[z]] = SCHWARZ 6 farbe[y] = SCHWARZ 7 farbe[p[p[z]]] = ROT 8 z = p[p[z]] 9 else if z == rechts[p[z]] 10 z = p[z] 11 LEFT-ROTATE(T, z) 12 farbe[p[z]] = SCHWARZ 13 farbe[p[p[z]]] = ROT 14 RIGHT-ROTATE(T, p[p[z]]) 15 else (wie der then-zweig, wobei rechts und links vertauscht sind) 16 farbe[wurzel[t]] = SCHWARZ AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 34
9.4.2 Entfernen aus Rot/Schwarz-Baum Variante der Tree-Delete-Operation für binäre Suchbäume, O(lg n) Nach Ausschneiden eines Knotens: Aufruf von RB-Delete- Fixup: Knoten werden neu gefärbt und Rotationen durchgeführt RB-DELETE(T, z) 1 if links[z] == NIL oder rechts[z] == NIL 2 y = z 3 else y = TREE-SUCCESSOR(z) 4 if links[y] NIL 5 x = links[y] 6 else x = rechts[y] 7 p[x] = p[y] 8 if p[y] == NIL 9 wurzel[t] = x 10 else if y == links[p[y]] 11 links[p[y]] = x 12 else rechts[p[y]] = x 13 if y z 14 schlüssel[z] = schlüssel[y] 15 kopiere y s Satellitendaten nach z 16 if farbe[y] == SCHWARZ 17 RB-DELETE-FIXUP(T, x) 18 return y RB-DELETE-FIXUP(T, x) 1 while x wurzel[t] und farbe[x] == SCHWARZ 2 if x == links[p[x]] 3 w = rechts[p[x]] 4 if farbe[w] == ROT 5 farbe[w] = SCHWARZ 6 farbe[p[x]] = ROT 7 LEFT-ROTATE(T, p[x]) 8 w = rechts[p[x]] 9 if farbe[links[w]] == SCHWARZ und farbe[rechts[w]] == SCHWARZ 10 farbe[w] = ROT 11 x = p[x] 12 else if farbe[rechts[w]] == SCHWARZ 13 farbe[links[w]] = SCHWARZ 14 farbe[w] = ROT 15 RIGHT-ROTATE(T, w) 16 w = rechts[p[x]] 17 farbe[w] = farbe[p[x]] 18 farbe[p[x]] = SCHWARZ 19 farbe[rechts[w]] = SCHWARZ 20 LEFT-ROTATE(T, p[x]) 21 x = wurzel[t] 22 else (wie then-zweig, wobei rechts und links vertauscht sind) 23 farbe[x] = SCHWARZ AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 35
Bezeichnung: Die Anzahl der schwarzen Knoten auf einem Pfad ausgehend von einem Knoten x (aber ohne diesen mitzuzählen) zu einem Blatt heißt die Schwarze Höhe von x: bh(x). Noch einmal Beispiel bh(13) = h(13): längster Pfad = bh(1) = AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 36
Rot-Schwarz-Bäume sind sehr gute Suchbäume, denn es gilt: Satz: Ein Rot-Schwarz-Baum mit n inneren Knoten hat höchstens die Höhe 2lg(n + 1), also h 2log(n + 1). Beweis: Zunächst wird gezeigt: der Teilbaum T x zu einem Knoten x besitzt mindestens 2 bh(x) 1 innere Knoten. Beweis durch Induktion über die Höhe von x. (1) Induktionsbasis: h(x) = 0 AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 37
(2) Induktionsschritt: Sei x ein innerer Knoten mit 2 Kindern. Jedes Kind hat, abhängig von seiner Farbe, entweder die schwarze Höhe bh(x) (Kind ist rot) oder bh(x) 1 (Kind ist schwarz). Die Höhe eines Kindes von x ist stets kleiner als die Höhe von x. Mit der Induktionsannahme können wir schließen, dass ein Kind von x mindestens 2 bh(x) 1 1 innere Knoten besitzt. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 38
Induktionsschritt (Forts.): Also enthält der Teilbaum zu x mindestens (2 bh(x) 1 1) + (2 bh(x) 1 1) + 1 = 2*(2 bh(x) 1 1) + 1 = 2 bh(x) 2 + 1= 2 bh(x) 1 innere Knoten. Weiterhin gilt: Gemäß der Rot-Schwarz-Eigenschaft muss gelten, dass mindestens die Hälfte der Knoten auf jedem Pfad von x zu einem Blatt schwarz sind. Sei h die Höhe des Baumes, dann gilt: Die Schwarz-Höhe der Wurzel ist mindestens h/2, es gilt somit: n 2 h/2 1, durch Umformung gilt: lg(n + 1) h/2 bzw. h 2lg(n + 1) AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 39
Beispiel AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 40
Bedeutung der bewiesenen Aussage: Die Operationen Search, Minimum oder auch Maximum können auf einem Rot-Schwarz-Baum in O(lg n) implementiert werden, da sie auf einem Baum der Höhe h in O(h) laufen und jeder Rot-Schwarz-Baum ein Suchbaum mit Höhe O(lg n) ist. Auch modifizierte Insert, Delete Operationen liegen in O(lg n). Fazit: Rot-Schwarz-Bäume sind effiziente Strukturen, sie ermöglichen eine schelle Suche etc. Sie setzen aber voraus, dass die Daten und Suchinformationen im Arbeitsspeicher vorliegen, also ein schneller Zugriff möglich ist. Aber: In der Praxis: sehr viele Daten sind zu speichern (z.b. in riesigen Kunden- und Produktdatenbanken). AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 41
Die Datenvolumina können nicht alle im Hauptspeicher abgelegt werden. Eine Auslagerung auf externe Festplatten ist notwendig: die Zugriffe sind dann sehr langsam! Lösung: B-Bäume 1972 (R. Bayer): geht über AuD-Stoff hinaus Das Ziel von B-Bäumen ist es, die Daten so zu organisieren, dass die Anzahl der Zugriffe auf externe Medien minimiert wird. B-Bäume sind balancierte Suchbäume Im Unterschied zu Rot-Schwarz-Bäumen kann ein Knoten in einem B-Baum viele Kinder besitzen, bis zu einigen tausend! D.h. der Verzweigungsfaktor eines B-Baumes kann sehr groß sein. Dadurch kann die Höhe eines B-Baumes erheblich geringer sein, als bei einem Rot/Schwarz-Baum. AuD, WS10/11, C. Eckert, Kapitel 9 Suchalgorithmen 42