• Keine Ergebnisse gefunden

§ Binäre Suchbäume § AVL-Bäume § B-Bäume § 2-3-4-Bäume und Rot-Schwarzbäume 3. Suchbäume

N/A
N/A
Protected

Academic year: 2021

Aktie "§ Binäre Suchbäume § AVL-Bäume § B-Bäume § 2-3-4-Bäume und Rot-Schwarzbäume 3. Suchbäume"

Copied!
94
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

3. Suchbäume

§ Binäre Suchbäume

- Begriffe und Eigenschaften (Wiederholung PROG 2) - Traversierung (Wiederholung PROG 2)

- Binäre Suchbäume (Wiederholung PROG 2) - Traversierung von Bäumen mit Elternzeiger

§ AVL-Bäume

§ B-Bäume

§ 2-3-4-Bäume und Rot-Schwarzbäume

(2)

Begriffe und Eigenschaften

Blatt

Wurzel Kante

Knoten

§ Ein Baum besteht aus einer Menge von Knoten und

einer Menge von gerichteten Kanten (von Elternknoten zu Kindknoten)

§ Es gibt genau einen Knoten, der keine eingehende Kante hat: die sogenannte Wurzel.

§ Alle anderen Knoten haben genau eine eingehende Kante.

§ Zyklen sind nicht erlaubt.

§ Knoten ohne ausgehende Kante heißen Blätter.

§ Kanten sind meistens nach unten gerichtet. Kantenrichtung wird dann oft weggelassen.

§ Spezialfall Binärbaum: Jeder Knoten hat maximal 2 Kinder (linkes bzw. rechtes Kind) k ist Elternknoten von s und t.

k

s t

(3)

Höhe eines Baums

Höhe = Maximale Anzahl von Kanten von seiner Wurzel zu einem Blatt.

Beispiel

10

6

5 12

3 7 11 15

3

1

0 0

2

1 0

0

Höhe für jeden Teilbaum

Beachte

• Ein Baum, der nur aus einem Knoten besteht, besitzt die Höhe 0.

(4)

Vollständiger Binärbaum

Beispiele

Eigenschaften

• Ein vollständiger Binärbaum mit n Knoten hat die Höhe h = ëlog

2

nû.

• Vollständige Binärbäume sind (bei einer gegebenen Knotenzahl) Binärbäume mit einer minimalen Höhe.

Ein vollständiger Binärbaum ist ein Binärbaum, bei der jede Ebene (bis auf die letzte)

vollständig gefüllt und die letzte Ebene von links nach rechts gefüllt ist.

(5)

Implementierung von Binärbäumen

§ Implementierung als verkettete Struktur:

Jeder Knoten hat jeweils eine Referenz für das linke und das rechte Kind.

A

G H

B C

D E F

class Node<K,V> { K key;

V value;

Node<K,V> left; // linkes Kind Node<K,V> right; // rechtes Kind }

I

A

C B

F E

D

H I G

root

(6)

Traversierung von Binärbäumen

Durchlaufreihenfolge

§ PreOrder: besuche Wurzel, besuche linken Teilbaum; besuche rechten Teilbaum;

§ PostOrder: besuche linken Teilbaum; besuche rechten Teilbaum; besuche Wurzel;

§ InOrder: besuche linken Teilbaum; besuche Wurzel; besuche rechten Teilbaum;

§ LevelOrder: besuche Knoten ebenenweise

Ziel

§ Das Besuchen aller Knoten in einer bestimmten Reihenfolge ist eine oft benötigte Operation.

Bemerkungen

§ Die Präfixe Pre, Post bzw. In bedeuten vorher, nachher und dazwischen.

Gemeint ist damit der Zeitpunkt, an dem die Wurzel besucht wird.

(7)

PreOrder-Durchlauf

Beispiel

*

- c

Durchlaufreihenfolge: * - a b c

static void preOrder(Node<K,V> p) {

if (p != null){

bearbeite(p);

preOrder(p.left);

preOrder(p.right);

} }

static class Node<K,V> { K key;

V value;

Node<K,V> left;

Node<K,V> right;

}

private Node<K,V> root;

//...

static void main(...) { preOrder(root);

}

(8)

PostOrder-Durchlauf

Beispiel

*

- c

a b

Durchlaufreihenfolge: a b – c *

(Entspricht der sog. Postfix-Notation für arithmetische Ausdrücke)

static void postOrder(Node<K, V> p) { if (p != null){

postOrder(p.left);

postOrder(p.right);

bearbeite(p);

} }

(9)

InOrder-Durchlauf für Binärbäume

Beispiel

*

- c

a b

Durchlaufreihenfolge: a - b * c

static void inOrder(Node<K, V> p) { if (p != null){

inOrder(p.left);

bearbeite(p);

inOrder(p.right);

} }

(10)

LevelOrder-Durchlauf

1

2 3

4 6

Durchlaufreihenfolge: 1, 2, 3, 4, 5, 6

static void levelOrder(Node<K,V> p) {

Queue<Node<K,V>> queue = new ArrayDeque<Node<K,V>>();

queue.add(p);

while (!queue.isEmpty()) {

Node<K,V> q = queue.remove();

if (q != null) { bearbeite(q);

queue.add(q.left);

queue.addd(q.right);

} } }

5

Die Knoten werden ebenenweise in einer Schlange gespeichert und in einer while-Schleife abgearbeitet.

(11)

Definition binärer Suchbäume

§ Ein binärer Suchbaum ist ein Binärbaum, bei dem für alle Knoten k folgende Eigenschaften gelten:

- Alle Schlüssel im linken Teilbaum sind kleiner als k - Alle Schlüssel im rechten Teilbaum sind größer als k

§ Beachte, dass die Zahlen hier eindeutig sein müssen. Es ist aber auch möglich, dass gleiche Zahlen mehrfach vorkommen dürfen, was kleine Änderungen in den Algorithmen erfordert.

Beispiele:

7

2 8

1 4

6

2 8

4

1

3

4

Degenerierter Suchbaum

(12)

Klasse BinarySearchTree

public class BinarySearchTree<K extends Comparable<? super K>, V> { private static class Node<K, V> {

private K key;

private V value;

private Node<K, V> left;

private Node<K, V> right;

private Node(K k, V v) { key = k;

value = v;

left = null;

right = null;

} }

private Node<K, V> root = null;

// ...

}

(13)

Suchen in binären Suchbäumen

Beispiel

3 7

2 8

1 4

6

searchR(3, root) liefert true

root

public V search(K key) {

return searchR(key, root);

}

private V searchR(K key, Node<K,V> p) { if (p == null)

return null;

else if (key.compareTo(p.key) < 0) return searchR(key, p.left);

else if (key.compareTo(p.key) > 0) return searchR(key, p.right);

else

return p.value;

}

(14)

Einfügen in binären Suchbäumen (1)

Idee

§ Um eine Zahl x einzufügen, wird zunächst nach x gesucht.

§ Falls x nicht bereits im Baum vorkommt,

endet die Suche erfolglos bei einer null-Referenz.

§ An dieser Stelle wird dann ein neuen Knoten mit Eintrag x eingefügt.

Beispiel 1: füge 6 ein

3 7

2 9

1 4

Suche von 6 endet

6 4 2

7

3

9

1

Ersetzte null durch neuen

Beispiel 2: füge 8 ein

9 2

4

3

7

1

Suche von 8 endet 6

9 7

8 2

4

3 1

Ersetzte null durch 6

(15)

Einfügen in binären Suchbäumen (2)

private V oldValue; // Rückgabeparameter public V insert(K key, V value) {

root = insertR(key, value, root);

return oldValue;

}

private Node<K,V> insertR(K key, V value, Node<K,V> p) { if (p == null) {

p = new Node(key, value);

oldValue = null;

}

else if (key.compareTo(p.key) < 0) p.left = insertR(key, value, p.left);

else if (key.compareTo(p.key) > 0)

p.right = insertR(key, value, p.right);

else { // Schlüssel bereits vorhanden:

oldValue = p.value;

p.value = value;

}

3 7

2 9

1 4

6 4 2

7

3

9

1

root = insert(6, root);

root root

(16)

Löschen in binären Suchbäumen (1)

§ Um eine Zahl x zu löschen, wird zunächst nach x gesucht.

Es sind dann 4 Fälle zu unterscheiden:

§ Fall „Nicht vorhanden“:

x kommt nicht vor. Dann ist nichts zu tun.

§ Fall „Keine Kinder“:

x kommt in einem Blatt vor (keine Kinder):

dann kann der Knoten einfach entfernt werden.

§ Fall „Ein Kind“:

Der Knoten, der x enthält, hat genau ein Kind:

s. nächste Folie

§ Fall „Zwei Kinder“:

Der Knoten, der x enthält, hat zwei Kinder:

s. übernächste Folie

Idee

(17)

Löschen in binären Suchbäumen (2)

Fall: der zu löschende Knoten k hat ein Kind

§ Überbrücke den Knoten k, indem der Elternknoten von k auf das Kind von k verzeigert wird (Bypass).

Beispiel: lösche Knoten k mit Inhalt 4

2 7

4

3

9

1 4

2 7

3

9

1

2 7

3 9

1

k k

(18)

Löschen in binären Suchbäumen (3)

Fall: der zu löschende Knoten k hat zwei Kinder

§ Ersetze den Knoten k durch den kleinsten Knoten k

min

im rechten Teilbaum von k.

§ Lösche dann k

min

.

§ Da der Knoten k

min

kein linkes Kind haben kann, kann das Löschen von k

min

wie im Fall „Ein Kind“ bzw. „Keine Kinder“ behandelt werden.

Beispiel: lösche Knoten k mit Inhalt 2

7 2

5 3

9 1

4 6

2 7

5 3

9 1

4 6

3 7

5 3

9 1

4 6

3 7

5 9 1

4 6

k k k

kmin kmin

(19)

Löschen in binären Suchbäumen (4)

private V oldValue; // Rückgabeparameter publicV remove(K key) {

root = removeR(k, root);

returnoldValue;

}

private Node<K,V> removeR(K key, Node<K,V> p) { if(p == null) { oldValue = null; }

else if(key.compareTo(p.key) < 0) p.left = removeR(key, p.left);

else if(key.compareTo(p.key) > 0) p.right = removeR(key, p.right);

else if(p.left == null || p.right == null) { // p muss gelöscht werden // und hat ein oder kein Kind:

oldValue = p.value;

p = (p.left != null) ? p.left : p.right;

} else{

// p muss gelöscht werden und hat zwei Kinder:

MinEntry<K,V> min = newMinEntry<K,V>();

p.right = getRemMinR(p.right, min);

oldValue = p.value;

p.key = min.key;

p.value = min.value;

private Node<K,V> getRemMinR(Node<K,V> p, MinEntry<K,V> min) { assertp != null;

if(p.left == null) { min.key = p.key;

min.value = p.value;

p = p.right;

} else

p.left = getRemMinR(p.left, min);

returnp;

}

private static classMinEntry<K, V> { private K key;

private V value;

}

§ getRemMinR löscht im Baum p den Knoten mit kleinstem Schlüssel und liefert Schlüssel und Daten des gelöschten Knotens über min zurück

§ MinEntry ist ein Hilfsdatentyp für den Rückgabe-

(20)

Analyse

Worst-Case

§ Im schlechtesten Fall kann ein binärer Suchbaum mit n Knoten zu einem Baum der Höhe n-1 entarten.

§ Damit: T

max

(n) = O(n)

Average-Case

§ In [Ottmann und Widmayer 2002] werden zwei Ergebnisse hergeleitet, die sich darin unterscheiden, welche Verteilung der Bäume angenommen wird.

§ Bäume mit n Knoten entstehen durch eine Folge von Einfüge-Operationen von n unterschiedlichen Elementen. Es wird angenommen, dass jede der n! möglichen Anordnungen der Elemente gleich wahrscheinlich ist.

Damit: T

mit

(n) = O(log

2

n)

§ Es wird angenommen, dass alle strukturell verschiedenen binären Suchbäume mit n Knoten gleichwahrscheinlich sind.

Damit: T

mit

(n) = O( ) n

(21)

3. Suchbäume

§ Binäre Suchbäume

- Begriffe und Eigenschaften (Wiederholung PROG 2) - Traversierung (Wiederholung PROG 2)

- Binäre Suchbäume (Wiederholung PROG 2) - Traversierung von Bäumen mit Elternzeiger

§ AVL-Bäume

§ B-Bäume

§ 2-3-4-Bäume und Rot-Schwarzbäume

(22)

Iterative Traversierung von Binärbäumen

Problem

§ In binären Suchbäumen gibt es für einen Knoten im allgemeinen keinen effizienten Zugriff auf seinen InOrder-Vorgänger bzw. -Nachfolger.

§ Daher ist mit der bisher besprochenen Datenstruktur für Suchbäume

keine effiziente Vorwärts- bzw. Rückwärtstraversierung mit Iteratoren machbar.

§ Wie erreicht man den Nachfolger von 8?

§ Wie erreicht man den Vorgänger von 6?

10

12 5

15 3 7

6 8 1

(23)

6 8 1

15

Bäume mit Elternzeigern

§ Erweitere jeden Knoten um einen Zeiger auf den Elternknoten.

10

5 12

7 3

(24)

Klasse BinarySearchTree mit Elternzeiger (1)

public class BinarySearchTree<K extends …, V> { private static class Node<K, V> {

private Node<K, V> parent; // Elternzeiger private K key;

private V value;

private Node<K, V> left;

private Node<K, V> right;

private Node(K k, V v) { key = k;

value = v;

left = null;

right = null;

parent = null;

} }

private Node<K, V> root = null;

// ...

§ Erweitere Klasse Node

um Elternzeiger parent:

(25)

Klasse BinarySearchTree mit Elternzeiger (2)

§ Überall, wo die Struktur des Baums geändert wird, wird zusätzlich der parent-Zeiger neu gesetzt:

expr1.left = expr2; expr1.left = expr2;

if (expr1.left != null)

expr1.left.parent = expr1;

10

5

...

...

...

expr1

expr2

...

...

...

10

5

expr1 und expr2 sind beliebige Ausdrücke vom Typ Node.

expr1

expr2

...

(26)

Klasse BinarySearchTree mit Elternzeiger (3)

§ Analog:

expr1.right = expr2; expr1.right = expr2;

if (expr1.right != null)

expr1.right.parent = expr1;

root = expr; root = expr;

if (root != null)

root.parent = null;

§ Beachte, dass der parent-Zeiger des root-Knotens den Wert null bekommt:

(27)

Beispiel: insert-Methode mit Elternzeiger

public V insert(K key, V value) { root = insertR(key, value, root);

if (root != null)

root.parent = null;

return oldValue;

}

private Node<K,V> insertR(K key, V value, Node<K,V> p) { if (p == null) {

p = new Node(key, value);

oldValue = null;

} else if (key.compareTo(p.key) < 0) { p.left = insertR(key, value, p.left);

if (p.left != null)

p.left.parent = p;

} else if (key.compareTo(p.key) > 0) { p.right = insertR(key, value, p.right);

if (p.right != null)

p.right.parent = p;

} else { // Schlüssel bereits vorhanden:

oldValue = p.value;

p.value = value;

}

return p;

(28)

Iterative Traversierung von Bäumen

§ Hier: nur Traversierung zum InOrder-Nachfolger.

Traversierung zum InOrder-Vorgänger geht analog.

§ Sei p der aktuelle Knoten. Gesucht ist der Nachfolger von p.

Wir unterscheiden zwei Fälle:

if (p.right != null)

p = leftMostDescendant(p.right);

else

p = parentOfLeftMostAncestor(p);

p

leftMostDescendant(p.right)

p

parentOfLeftMostAncestor(p)

...

... ...

...

... ...

(29)

6 8 1

15

leftMostDescendant

10

5 12

7 3

InOrder-Nachfolger von p = 5:

leftMostDescendant(p.right) = 6

(30)

6 8 1

15

parentOfLeftMostAncestor

10

5 12

7 3

InOrder-Nachfolger von p = 8:

parentOfLeftMostAncestor(p) = 10

(31)

Implementierung von leftMostDescendant

private Node<K,V> leftMostDescendant(Node<K,V> p) { assert p != null;

while (p.left != null) p = p.left;

return p;

}

p

leftMostDescendant(p)

...

...

(32)

Implementierung von parentOfLeftMostAncestor

private Node<K,V> parentOfLeftMostAncestor(Node<K,V> p) { assert p != null;

while (p.parent != null && p.parent.right == p) p = p.parent;

return p.parent; // kann auch null sein }

p

parentOfLeftMostAncestor(p)

...

...

...

(33)

Traversierungsschleife für InOrder-Nachfolger

// Erster Knoten:

Node<K,V> p = null;

if (root != null)

p = leftMostDescendant(root);

while( p != null) {

System.out.print(p.key + ", ");

if (p.right != null)

p= leftMostDescendant(p.right);

else

p = ParentOfLeftMostAncestor(p);

}

6 8 1

15 10

5 12

7 3

§ Traversersierung-Schleife ergibt:

(34)

3. Suchbäume

§ Binäre Suchbäume

- Begriffe und Eigenschaften (Wiederholung PROG 2) - Traversierung (Wiederholung PROG 2)

- Binäre Suchbäume (Wiederholung PROG 2) - Traversierung von Bäumen mit Elternzeiger

§ AVL-Bäume

§ B-Bäume

§ 2-3-4-Bäume und Rot-Schwarzbäume

(35)

Definition von AVL-Bäumen

§ Ein binärer Suchbaum heißt AVL-Baum oder (höhen)balanzierter Baum, falls sich für jeden Knoten die Höhen der beiden Teilbäume um höchstens 1 unterscheiden.

§ Die Abkürzung AVL geht zurück auf Adelson-Velskij und Landis.

Beispiel für AVL-Baum: Beispiel für Nicht-AVL-Baum

10

6

5 12

3 7 11 15

10

8

5 12

7

Höhe des Teilbaums Höhenunterschied

= Höhe rechter Teilbaum

− Höhe linker Teilbaum (Beachte: Höhe eines leeren Teilbaums ist -1.)

3

1

0 0

2

1 0

0 0

0

1 2

3 -1

0

0 0 0

0 0

+1

+2 0

-2

-1 +1

Eigenschaft

(36)

Rotationen (1)

Zentrale Eigenschaft von AVL-Bäumen:

Ein unbalanzierter Baum, der einen Höhenunterschied von -2 (linkslastiger Baum) oder +2 (rechtslastiger Baum) hat und dessen Teilbäume ausbalanziert sind, lassen sich durch eine einfache Rotationsoperation ausbalanzieren.

Fall A: Baum ist linkslastig, d.h. Höhenunterschied = -2

p

q

Teilbäume A, B, und C sind ausbalanziert und können auch leer sein.

h+1 -2

Unterfall A1: linker Teilbaum hat Höhenunterschied -1 oder 0:

A

C h-1

B

h h od.

h-1 -1 oder 0

Rotate Right

q

p

h od.

h+1 A

C B

h

h od.

h-1 1 od. 0

h-1

(37)

Rotationen (2)

Fall A: Baum ist linkslastig, d.h. Höhenunterschied = -2

p

q h+1 -2

Unterfall A2: linker Teilbaum hat Höhenunterschied +1:

A

D h-1

B

h +1

Rotate Left

Right

r

p

A C D

h

0

C h-1 r

h-1 od.

h-2

h-2 od.

h-1

1.

2.

B q h

Teilbäume B und C haben aber nicht beide die Höhe h-2.

(38)

Rotationen (3)

Fall B: Baum ist rechtslastig, d.h. Höhenunterschied = +2

p

q h+1 +2

Unterfall B1: rechter Teilbaum hat Höhenunterschied 0 oder +1:

B A

h-1

C h od.

h-1 h

0 oder +1

Rotate Left

q

p h od.

h+1

0 od. -1

A

C h

B h-1

0 oder +1

h od.

h-1

(39)

Rotationen (4)

Fall B: Baum ist rechtslastig, d.h. Höhenunterschied = +2 Unterfall B2: rechter Teilbaum hat Höhenunterschied -1:

Rotate

Right Left

r

q

A C D

h

0 p

h+1 q +2

D A

h-1

C h

-1

B

r h-1

h-1 od.

h-2 h-2 od.

h-1

1.

2.

B p h

Teilbäume B und C haben aber nicht beide die Höhe h-2.

(40)

Idee für Algorithmus:

1) Füge ein bzw. lösche wie bei binären Suchbäumen.

2) Gehe dann von der Einfügestelle bzw. Löschstelle bis zur Wurzel

und balanziere falls notwendig mit einer der 4 Rotatationsoperationen lokal aus.

Einfügen und Löschen in AVL-Bäumen

Bemerkungen:

§ Da der Baum vor dem Einfügen bzw. Löschen ausbalanziert war, haben alle Teibäume einen Höhenunterschied von -1, 0 oder +1.

Damit können nach dem Schritt 1) nur die Fälle A1, A2, B1 oder B2 auftreten.

§ Schritt 2) lässt sich geschickt beim Aufstieg aus der Rekursion durchführen (siehe balance-Aufruf in der Methode insertR auf Seite 3-44).

§ Es lässt sich zeigen, dass beim Einfügen insgesamt maximal eine der 4 Rotationsoperationen notwendig ist.

§ Beim Löschen müssen i.a. mehrere Rotationsoperationen durchgeführt werden

(siehe Beispiel 2 auf Seite 3-49 und 3-50)

(41)

4

3 5 3

2

4

Beispiel zu Einfügen in AVL-Bäumen (1)

1

+1 +2

Rotate Left (Fall B1)

2

1 3 2

4

5 2

1 3

4

Füge 5 ein 1

Gehe vom Knoten 5 in Richtung Wurzel bis zum ersten

unbalanzierten Teilbaum.

(42)

4

7

5

14

Beispiel zu Einfügen in AVL-Bäumen (2)

Beispiel:

Füge 13 ein

Gehe bis zum ersten unbalanzierten

Teilbaum.

2

1 3

6

5 14

7 15 4

15 14 6

7 4

13 2

1 3 5

15 14 6

7 4

2

1 3 5

+2 1.

2. Rotate

Right Left (Fall B2)

15 13

2

1 3 6

(43)

Algorithmen (1)

§ Node wie bei binären Suchbäumen.

Zusätzlich wird für jeden Knoten im Baum noch die Höhe des entsprechenden Teilbaums abgespeichert.

private static class Node<K, V> { int height;

K key;

V value;

Node<K, V> left;

Node<K, V> right;

private Node(K k, V v) { height = 0;

key = k;

value = v;

left = null;

right = null;

} }

private int getHeight(Node<K,V> p) { if (p == null)

return -1;

else

return p.height;

}

private int getBalance(Node<K,V> p) { if (p == null)

return 0;

else

return getHeight(p.right) - getHeight(p.left);

}

(44)

Algorithmen (2)

§ Erweitere die rekursive insertR-Operation für binäre Suchbäume um eine Balanzieroperation, die beim rekursiven Aufstieg durchgeführt wird.

private Node<K,V> insertR(K key, V value, Node<K,V> p) { if (p == null) {

p = new Node(key, value);

oldValue = null;

}

else if (key.compareTo(p.key) < 0) p.left = insertR(key, value, p.left);

else if (key.compareTo(p.key) > 0)

p.right = insertR(key, value, p.right);

else { // Schlüssel bereits vorhanden:

oldValue = p.value;

p.value = value;

}

p = balance(p);

return p;

}

§ Die removeR- und getRemMinR-Operation werden analog erweitert.

(45)

Algorithmen (3)

private Node<K,V> balance(Node<K,V> p) { if (p == null)

return null;

p.height = Math.max(getHeight(p.left), getHeight(p.right)) + 1;

if (getBalance(p) == -2) {

if (getBalance(p.left) <= 0) p = rotateRight(p);

else

p = rotateLeftRight(p);

}

else if (getBalance(p) == +2) { if (getBalance(p.right) >= 0)

p = rotateLeft(p);

else

p = rotateRightLeft(p);

}

return p;

}

Fall A1 Fall A2

Fall B1 Fall B2

Höhe aktualisieren.

(46)

Algorithmen (3)

p

q

C

Rotate

Right

q

p A

private Node<K,V> rotateRight(Node<K,V> p) { assert p.left != null;

Node<K, V> q = p.left;

p.left = q.right;

q.right = p;

p.height = Math.max(getHeight(p.left), getHeight(p.right)) + 1;

q.height = Math.max(getHeight(q.left), getHeight(q.right)) + 1;

return q;

}

(47)

Algorithmen (4)

private Node<K,V> rotateLeft(Node<K,V> p) { // analog zu rotateRight

}

private Node<K,V> rotateLeftRight(Node<K,V> p) { assert p.left != null;

p.left = rotateLeft(p.left);

return rotateRight(p);

}

private Node<K,V> rotateRightLeft(Node<K,V> p) { assert p.right != null;

p.right = rotateRight(p.right);

return rotateLeft(p);

}

(48)

Beispiel 1 zu Löschen in AVL-Bäumen

Lösche 10

Rotate Left (Fall B1) 5

3 9

4 18 26

20

25 13

15 10

17 19

5

3 9

4 18 26

20

25 13

15 13

17 19

5

3 9

4 18 26

20 15 25

13

17 19 +2

5

3 9

4 19 26

20 18 25

13

17 15

(49)

Beispiel 2 zu Löschen in AVL-Bäumen (1)

Lösche 5

Rotate Left Right

(Fall A2) 5

3 9

4 18 26

20

25 13

15 10

17 19

9

3 9

4 18 26

20

25 13

15 10

17 19

9-2 3

4 18 26

20

25 13

15 10

4

3 9

18 26 20

25 13

15 10

(50)

Beispiel 2 zu Löschen in AVL-Bäumen (2)

Rotate Right Left

(Fall B2) 4 +2

3 9

18 26 20

25 13

15 10

19 17

4

3 9 26

18

20 13 25

15 10

17 19

(51)

3. Suchbäume

§ Binäre Suchbäume

- Begriffe und Eigenschaften (Wiederholung PROG 2) - Traversierung (Wiederholung PROG 2)

- Binäre Suchbäume (Wiederholung PROG 2) - Traversierung von Bäumen mit Elternzeiger

§ AVL-Bäume

§ B-Bäume

§ 2-3-4-Bäume und Rot-Schwarzbäume

(52)

Definition von B-Bäumen der Ordnung m

1. Balanzierung: Jedes Blatt hat die gleiche Tiefe.

2. Anzahl Schlüssel:

- maximal m-1 (einschl.).

- minimal ém/2ù -1 (einschl.). Ausnahme Wurzel: minimal 1 Schlüssel.

3. Anzahl Kinder:

Jeder Knoten (außer den Blättern) mit i vielen Schlüsseln hat genau i+1 Kinder.

(Beachte, dass ein B-Baum aus genau einem Knoten – die Wurzel – bestehen darf) 4. Schlüsselordnung:

Für jeden Knoten K mit i-1 Schlüsseln k

0

, k

1

, …, k

i-2

und i Kindern mit ihren Teilbäumen B

0

, B

1

, …, B

i-1

gilt folgende Beziehung:

Schlüssel in B

0

< k

0

< Schlüssel in B

1

< k

1

< Schlüssel in B

2

< … Schlüssel in B

i-2

< k

i-2

< Schlüssel in B

i-1

.

k0 k1 … ki-2 Knoten K mit seinen i-1 Schlüsseln

B B B … B B

i Kinder mit ihren Teilbäumen

(53)

Beispiele für B-Bäume der Ordnung m = 4

10 30 35 50

20 60

70 90 20 60

10

20

60 90

B-Baum der Höhe 0 B-Baum der Höhe 1

B-Baum der Höhe 2

(54)

Implementierung von B-Bäumen der Ordnung m

§ Jeder Knoten besteht aus

- einem statischen Feld der Größe m-1 für die Schlüssel und - einem statischem Feld der Größe m für die Zeiger

auf die Kinder.

k0 k1 … ki-2

...

k0 k1 … ki-2 ...

Feld für m-1 Schlüssel

Feld für m Zeiger auf die Kinder

… ...

...

(55)

Suchen in B-Bäumen

Beispiel: Suchen nach k = 43

V search(K key, Node<K,V> p) { if (p == 0)

return null; // nicht gefunden;

suche key in Schlüsselmenge von Knoten p (beispielsweise mit binärer Suche);

if (key gefunden) return Daten;

p = Teilbaum, in dem key liegen könnte;

return search(key, p);

}

10 30 35 50

20 60

70 90 Rekursiver Aufruf

(56)

Einfügen in B-Bäumen

V insert(K key, V value, Node<K,V> p) { suche Schlüssel key im Baum p;

if (key gefunden) {

speichere Daten in oldValue;

ersetze Daten durch value;

return oldValue;

}

füge key, value an der Blattstelle ein, wo die Suche beendet wurde;

if (kein Schlüsselüberlauf) return null;

for (alle Knoten k vom aktuellen Knoten bis zur Wurzel) { if (Schlüsselüberlaufbei k)

führeSplit-Operation für k durch;

else

return null;

} }

§ Einfügen immer in einem Blatt.

§ Schlüsselüberlauf, falls Anzahl der Schlüssel gleich m.

§ insert kann wie bei AVL- Bäumen rekursiv realisiert werden.

Die Behandlung der Schlüssel- überläufe geschieht dann beim rekursiven Aufstieg.

§ Muss die Wurzel gesplittet

werden, dann entsteht eine

neue Wurzel (siehe Beispiel)

(57)

Split-Operation bei Schlüsselüberlauf

k0 k1 … kmit-1 kmit kmit+1 … km-1 Aktueller Knoten mit Schlüsselüberlauf:

Knoten enthält genau m Schlüssel

... ...

k0 k1 … kmit-1 kmit+1 … km-1

Split- Operation Elternknoten

Teile Schlüssel- menge an der Stelle mit = ëm/2û

... kmit ...

(58)

Beispiel 1: Einfügen von 82

10 30 35 50

20 60

70 90

11 12 15

5 7 21 24 33 38 43 45 52 55 65 67 69 80 85 96

10 30 35 50

20 60

70 90

1) Suchen von 82

2) 82 einfügen;

keine Split-Operation

notwendig, da genügend Platz

(59)

Beispiel 2: Einfügen von 39

10 30 35 50

20 60

70 90

11 12 15

5 7 21 24 33 38 44 45 52 55 65 67 69 96

10 30 35 50

20 60

70 90

1) Suchen und Einfügen von 39

2) Schlüsselüberlauf

80 82 85

(60)

Beispiel 2: Einfügen von 39 (Fortsetzung)

10 30 35 50

20 60

70 90

11 12 15

5 7 21 24 33 38 39 44 45 52 55 65 67 69 80 82 85 96

3) Split-Operation führt zu weiterem Überlauf

10 30 35 44 50

20 60

70 90

11 12 15

5 7 21 24 33 38 39 45 52 55 65 67 69 80 82 85 96

(61)

Beispiel 2: Einfügen von 39 (Fortsetzung)

10 30 35 44 50

20 60

70 90

11 12 15

5 7 21 24 33 38 39 52 55 65 67 69 80 82 85 96

10 30 35

20 44 60

70 90 50

5) Split-Operation und fertig!

45

(62)

Beispiel 3: Erzeugen eines neuen Knotens bei einer Einfüge-Operation

20 40 50

50 10 20

10 wird gesucht und eingefügt.

Überlauf!

10 20 40 50

Split-Operation anwenden, da nicht genügend Platz.

Dabei wird ein neuer Knoten erzeugt.

40

B-Baum mit genau einem Knoten

mit 3 Schlüsseln

(63)

Löschen in B-Bäumen

V remove(K key, Node<K,V> p) { suche Schlüssel key im Baum;

if (key nicht gefunden) return null;

if (key befindet sich im Blatt)

speichere Daten in oldValue und lösche key;

else

speichere Daten in oldValue und ersetze key (mit value)

durch nächst größeren Schlüssel key’ (mit value') und lösche key’;

// key’ befindet sich im rechten Teilbaum von key ganz links in einem Blatt for (alle Knoten k vom aktuellen Knoten bis zur Wurzel) {

if ( Schlüsselunterlaufbei k) {

if (Geschwisterknoten kann Schlüssel abgeben)

Übernahme von Schlüsseln vom Geschwisterknoten;

else

Verschmelze Knoten k mit einem Geschwisterknoten;

} else

§ Löschen immer in einem Blatt.

§ Schlüsselunterlauf, falls

Anzahl der Schlüssel kleiner als ém/2ù -1.

§ remove kann wie bei AVL- Bäumen rekursiv realisiert werden.

Die Behandlung der Schlüsselunterläufe geschieht dann beim rekursiven Aufstieg.

§ Hat die Wurzel genau 2

Kinder, die verschmolzen

werden müssen, dann wird

die Wurzel leer und muss

entfernt werden (siehe

(64)

Behandlung eines Schlüsselunterlaufs: Übernahme von Schlüssel

Aktueller Knoten;

Schlüsselmenge ist zu klein

k1 k2 Elternknoten

Rechter Geschwisterknoten

§ Prüfe zuerst, ob linker Geschwisterknoten Schlüssel abgeben kann. Falls nicht, dann prüfe rechten Knoten.

§ Abgabe von Schlüsseln, so dass Knoten in etwa gleich groß werden.

§ Verfahren kann dann abgebrochen werden,

da im Elternknoten kein Schlüsselunterlauf entstehen kann.

Linker

Geschwisterknoten

(65)

Übernahme von Schlüssel (hier vom linken Geschwisterknoten)

Aktueller Knoten

Elternknoten

... ...

Rechter Geschwisterknoten

Linker Geschwisterknoten gibt dem aktuellen Knoten gerade soviel Schlüssel (und Kindzeiger) ab, so dass sich die Knotenanzahl um maximal 1 unterscheidet.

... g1 g2 ...

Linker Geschwisterknoten

... g2 ... k1 ... ...

... k1 k2 ...

g1 k2

... ... ... ...

... ...

... ...

(66)

Behandlung eines Schlüsselunterlaufs: Verschmelzung

Aktueller Knoten;

Schlüsselmenge ist zu klein

k1 k2 Elternknoten

Rechter Geschwisterknoten Linker

Geschwisterknoten

§ Beide Geschwisterknoten haben zu wenig Schlüssel, um Schlüssel abgeben zu können.

§ Führe daher Verschmelzung mit einem Geschwisterknoten durch.

§ Fasse aktuellen Knoten mit linkem Geschwisterknoten (falls vorhanden) zusammen.

Sonst fasse mit rechtem Geschwisterknoten zusammen.

§ Bei Elternknoten wird ein Schlüssel nach unten verschoben.

Daher kann nun beim Elternknoten ein Schlüsselunterlauf vorkommen.

Führe daher Verfahren gegebenenfalls rekursiv beim Elternknoten fort.

(67)

Verschmelzung (hier mit linkem Geschwisterknoten)

Aktueller Knoten

Elternknoten

Rechter Geschwisterknoten

Fasse aktuellen Knoten mit

linkem Geschwisterknoten zusammen Linker Geschwisterknoten

... k1 k2 ...

..

. ..

.

... k2 ...

... ...

...

... ...

(68)

Beispiel 1: Löschen von 96

10 30 35

20 44 60

70 90

11 12 15

5 7 21 24 33 38 39 45 52 55 65 67 69 80 82 85 96 50

1) Suchen und

Löschen von 96

führt zu Unterlauf

(69)

Beispiel 1: Löschen von 96 (Fortsetzung)

10 30 35

20 44 60

70 90

11 12 15

5 7 21 24 33 38 39 45 52 55 65 67 69 80 82 85

50

2) Linker Geschwisterknoten kann Schlüssel abgeben.

Fertig!

10 30 35

20 44 60

70 85 50

(70)

Beispiel 2: Löschen von 80

1) Suchen und Löschen von 80 führt zu Unterlauf

10 30 35

20 44 60

70

11 12 15

5 7 21 24 33 38 39 51 52 53 65 80

50 55

58

(71)

Beispiel 2: Löschen von 80 (Fortsetzung)

2) Verschmelzung mit linkem Geschwisterknoten

führt zu weiterem Unterlauf.

10 30 35

20 44 60

10 30 35

20 44 60

70

11 12 15

5 7 21 24 33 38 39 51 52 53 65

50 55

58

50 55

(72)

Beispiel 2: Löschen von 80 (Fortsetzung)

3) Linker Geschwisterknoten kann Schlüssel abgeben.

Fertig!

10 30 35

20 44 60

11 12 15

5 7 21 24 33 38 39 51 52 53 65 70

50 55

58

10 30 35

20 44 55

50 60

(73)

Beispiel 3: Löschen von 60

1) Suchen und Löschen von 60

2) Schüssel 60 befindet sich nicht in Blatt: daher durch nächst größeren Schlüssel 65 ersetzen und Schlüssel 65 löschen.

3) Kein Schlüsselunterlauf, daher fertig!

10 30 35

20 44 60

70 85

11 12 15

5 7 21 24 33 38 39 45 52 55 65 67 69 80 82 90

50

10 30 35

20 44 65

70 85 50

(74)

50

Beispiel 4: Wurzel muss entfernt werden

40

20

1) Suchen und Löschen von 50

2) Schlüsselunterlauf;

Verschmelzung mit Geschwisterknoten

20 40

3) Schlüsselunterlauf in der Wurzel;

Wurzel entfernen

20 40

(75)

Analyse (1)

Höhe eines B-Baumes mit n Schlüsseln:

§ Im schlechtesten Fall hat die Wurzel 2 Kinder und jeder andere Nicht-Blatt- Knoten ém/2ù viele Kinder.

§ Damit ergibt sich eine maximale Höhe von (siehe [Ottmann u. Widmayer]):

h ≤ log

ém/2ù

(n+1)/2

Beispiel:

§ Für m = 256 und n = 10

9

ergibt sich eine maximale Höhe von h £ 4.1

Aufwand für Suchen, Einfügen und Löschen:

§ Da die Höhe eines B-Baums durch log

ém/2ù

(n+1)/2 beschränkt ist, ergibt sich eine maximale Laufzeit von:

T(n) = O( log

ém/2ù

(n) )

(76)

Analyse (2)

Speicherplatzausnutzung:

§ Eine naheliegende Implementierung eines B-Baums sieht für jeden Knoten ein statisches Feld der Größe m für die Schlüssel und Zeiger auf die Kinder vor.

§ Da jeder Knoten (außer Wurzel) zwischen ém/2ù -1 und m-1 viele Schlüssel enthält, stellt sich die Frage, wie groß die Speicherplatzausnutzung ist.

§ Es gilt folgende Eigenschaft (siehe [Ottmann u. Widmayer]):

Wenn eine zufällig gewählte Folge von n Schlüsseln in einen anfangs leeren B-Baum der Ordnung m eingefügt werden, dann ist eine

Speicherplatzausnutzung zu erwarten von:

ln(2) » 69 %.

§ Falls eine absteigend oder aufsteigend sortierte Folge in einen leeren B-Baum einfügt wird, ergibt sich eine besonders schlechte Speicherplatzausnutzung, die aber immer noch bei ca. 50 % liegt.

§ Etwas lindern lässt sich das Problem, indem nicht bei jedem Knotenüberlauf eine

Splittoperation durchgeführt wird, sondern zuvor geprüft wird, ob Schlüssel an

Geschwisterknoten abgegeben werden können.

(77)

Anwendungen

Externe Suchverfahren

§ Eine der wichtigsten Anwendungen von B-Bäume sind externe Suchverfahren (z.B.

im Datenbankbereich). Die Menge der Datensätze ist dabei so groß, dass sie nur auf Hintergrundspeicher wie beispielsweise Festplatte abgespeichert werden kann.

§ Die Knotengröße m wird dann so gewählt, dass mit einem Festplattenzugriff die gesamten Daten eines Knotens (d.h. Schlüssel und Zeiger; Indexseite) gelesen werden können.

§ Die Datensätze selbst sind auf der Platte gespeichert.

Beispiel:

§ Wählt man beispielsweise m = 256 und sind ca. n = 10

9

Datensätze zu verwalten,

dann ergibt sich ein B-Baum etwa der Höhe 4. Speichert man die beiden obersten

Ebenen des B-Baums (d.h. Wurzel und seine Kinder) im Hauptspeicher (das sind

maximal 255 + 256*255 = 65535 Schlüssel), dann kommt man im schlechtesten Fall

bei einer Suchoperation mit 3 Plattenzugriffe aus.

(78)

Variante: B * -Baum

§ Zusätzliche Forderung:

jeder Knoten (außer der Wurzel) muss mindestens zu 2/3 gefüllt sein.

§ Vorteil:

bessere Speicherplatzausnutzung und geringere Höhe des Baumes.

§ Nachteil:

bei den Operationen Einfügen und Löschen kommt ein Überschreiten der Maximal-

bzw. Minimalzahl der Schlüssel je Knoten im Vergleich zum B-Baum häufiger vor.

(79)

Variante: B + -Baum

§ Die Datensätze werden nur in den Blättern abgespeichert.

§ Um die Bereichssuche zu unterstützen (finde alle Datensätze mit Schlüssel k Î [k1, k2]), werden die Blätter miteinander verkettet.

§ In den Nicht-Blatt-Knoten stehen nur Schlüssel und Zeiger zu Navigationszwecken.

Der i-te Schlüssel k

i

befindet sich noch zusätzlich als kleinster Schlüssel im Teilbaum B

i+1

§ Für die Anzahl der Schlüssel in den Blättern kann eine andere Minimal- und Maximalzahl gelten.

8 48 51

21 66 87

95 97

8 12 15 21 24 51 53 72 75 87 88 89 95 96 97

72

2 4 6 48 66

(80)

3. Suchbäume

§ Binäre Suchbäume

- Begriffe und Eigenschaften (Wiederholung PROG 2) - Traversierung (Wiederholung PROG 2)

- Binäre Suchbäume (Wiederholung PROG 2) - Traversierung von Bäumen mit Elternzeiger

§ AVL-Bäume

§ B-Bäume

§ 2-3-4-Bäume und Rot-Schwarzbäume

(81)

2-3-4-Bäume

§ B-Bäume der Ordnung 4 nennt man auch 2-3-4-Bäume.

Ein Nicht-Blatt-Knoten hat 2, 3 oder 4 Kinder.

10 30 35 50

20 60

70 90

11 12 15

5 7 21 24 33 38 43 45 52 55 65 67 69 80 85 96

§ 2-3-4-Bäume sind eine sehr gut geeignete Alternative zu AVL-Bäumen.

§ 2-3-4-Bäume lassen sich auch als Top-Down-Variante realisieren:

beim Einfügen bzw. Löschen wird der Baum mit einer Schleife von der Wurzel in

Richtung der Blätter durchlaufen.

(82)

2-3-4-Bäume und Rot-Schwarz-Bäume (1)

k1 k2 k3

k1 k2 oder

§ Eine beliebte Implementierungsvariante von 2-3-4-Bäumen sind Rot-Schwarz-Bäume, die mit einer wesentlich einfacheren Datenstruktur auskommen (wie bei binären

Suchbäumen) und außerdem top-down realisiert werden können.

Beispiel: Java-Collections und STL-Bibliothek von C++.

§ Rot-Schwarz-Bäume sind binäre Suchbäume, dessen Knoten entweder rot oder schwarz sind und für die bestimmte Färbungsregeln gelten.

§ Ein 2-3-4-Baum wird in ein Rot-Schwarz-Baum transformiert, indem

3-Knoten (Knoten mit 3 Schlüsseln) und 2-Knoten mittels einer einfachen Regel ersetzt werden. 1-Knoten bleiben unverändert.

k3 k1

k1 k2

k2

k2 k1

(83)

2-3-4-Bäume und Rot-Schwarz-Bäume (2)

15 50 60 70

30

5 10 20 40 45 55 65 80 85 90

Beispiel

5

15

10 20

30

60

40 55 65 85

50 70

(84)

Färbungsregeln von Rot-Schwarz-Bäumen

Ein Rot-Schwarz-Baum ist ein binärer Suchbaum mit folgenden Färbungsregeln:

(1) Jeder Knoten ist entweder rot oder schwarz.

(2) Die Wurzel ist immer schwarz.

(3) Ein roter Knoten darf kein rotes Kind haben.

(4) Jeder Pfad von der Wurzel zu einem Blatt hat die die gleiche Anzahl an schwarzen Knoten.

Bemerkung:

§ Durch die 4 Färbungsregeln wird gewährleistet, dass ein Rot-Schwarz Baum mit den Transformationsregeln von Seite 3-82 auch wieder

einem 2-3-4 Baum entspricht.

§ Rot-Schwarz-Bäume werden mit derselben Datenstruktur wie binäre

Suchbäume realisiert. Jedoch wird zusätzlich ein Bit für die Farbe

(rot oder schwarz) verwendet.

(85)

Einfügen eines Schlüssels in einen Rot-Schwarz-Baum (1)

§ durchlaufe Rot-Schwarz-Baum rsb mit einer Schleife von seiner Wurzel bis zu

demjenigen Blatt, unter dem der neue Knoten mit Schlüssel key eingefügt werden soll;

§ füge neuen roten Knoten mit Schlüssel key ein;

q = Wurzel des Baums rsb;

while (q ist nicht das Blatt, unter dem key eingefügt werden soll) { evtl. Farbwechsel (FW);

evtl. eine der Rotationsoperationen R, LR, L, RL;

if (key < q.key) q = q.left;

else if(key > q.key) q = q.right;

else

// Schlüssel bereits vorhanden; mache nichts;

}

if (key < q.key)

q.left = newRedNode(key);

else

q.right = newRedNode(key);

evtl. eine der Rotationsoperationen R, LR, L, RL;

§ da der neu eingefügte Knoten rot ist, ist die Einhaltung der Regel (4) gewährleistet

(86)

Einfügen eines Schlüssels in einen Rot-Schwarz-Baum (2)

c2 c1

q

c2 c1

q

§ Wende auf Knoten q, der zwei rote Kinder hat, einen Farbwechsel FW durch.

Falls q die Wurzel ist, dann bleibt q schwarz.

FW

§ Falls durch den Farbwechsels (FW) oder durch Einfügen eines neuen roten Knotens zwei hintereinanderfolgende rote Knoten entstehen, dann wird

eine der Rotationsoperationen R, LR, L oder RL durchgeführt.

(87)

C

Rotationsoperation R

s p

g

B A

q

R

g p

B

C A s

q

§ Rotation wird um Knoten p nach rechts durchgeführt.

p (parent) und g (grandparent) werden dabei umgefärbt.

§ Der Knoten s (Geschwister von p vor Anwendung der Rotation) muss

schwarz sein. (Begründung in [Weiss 2011])

(88)

C

Rotationsoperation LR

s p

g

B1 B2

q A

p g

q

B1 B2 A

C s

§ Rotation wird um Knoten p nach links und dann um q nach rechts durchgeführt. q und g werden dabei umgefärbt.

§ Der Knoten s (Geschwister von p vor Anwendung der Rotation) muss schwarz sein. (Begründung in [Weiss 2011])

Daher keine weitere Verletzung der Farbregel.

(2) R

(1) L

(89)

C

Rotationsoperation L

s p

g

B

A q

L

q p

B s C

A g

§ Rotation wird um Knoten p nach links durchgeführt.

p (parent) und g (grandparent) werden dabei umgefärbt.

§ Der Knoten s (Geschwister von p vor Anwendung der Rotation) muss

schwarz sein. (Begründung in [Weiss 2011])

(90)

C

Rotationsoperation RL

s p

g

B1 B2

q A

g p

q

B1 B2 A

C s

§ Rotation wird um Knoten p nach rechts und dann um q nach links durchgeführt. q und g werden dabei umgefärbt.

§ Der Knoten s (Geschwister von p vor Anwendung der Rotation) muss schwarz sein. (Begründung in [Weiss 2011])

Daher keine weitere Verletzung der Farbregel.

(1) R (2) L

(91)

Beispiel (1)

5

15

10 20

30

70

55

50 65 90

60 85

40

80

§ Einfügen von 45.

§ Der Baum wird bei der Wurzel 30 beginnend top down durchlaufen:

30, 70, 60, 50.

§ Bei 50 wird ein Farbwechsel FW durchgeführt.

5

15

10 20

30

70

55

50 65 90

60 85

40

80

(92)

Beispiel (2)

§ Durch den Farbwechsel wird eine Rechtsrotation R notwendig

5

15

10 20

30

70

55

50 65 90

60 85

40

80 5

15

10 20

30

60

40 55

50 70

65

90 85 80

(93)

Beispiel (3)

§ Der Durchlauf kann bei Knoten 50 fortgesetzt werden. Dadurch wird als nächstes Knoten 40 besucht.

§ Der neue Knoten 45 kann rechts von 40 als roter Knoten eingefügt werden.

§ Fertig!

5

15

10 20

30

60

40 55

50 70

65

90 85 80

5

15

10 20

30

60

40 55

50 70

65

90 85 80 45

(94)

Löschen eines Schlüssels in einem Rot-Schwarz-Baum

§ Grundsätzliche Idee: Gelöscht wird immer ein rotes Blatt.

§ Zunächst wird der zu löschende Knoten durch iterativen top-down-Durchlauf gesucht.

§ Hat der zu löschende Knoten zwei Kinder, dann wird er durch den kleinsten Knoten min im rechten Teilbaum ersetzt. min kann nur ein Kind haben und wird als

nächstes gelöscht.

§ Hat der zu löschende Knoten genau ein rechtes Kind, dann wird er durch den kleinsten Knoten min im rechten Teilbaum ersetzt.

min kann höchstens ein Kind haben und wird als nächstes gelöscht.

§ Hat der zu löschende Knoten genau ein linkes Kind, dann wird es durch den größten Knoten max im linken Teilbaum ersetzt.

max kann höchstens ein Kind haben und wird als nächstes gelöscht.

§ Das Verfahren terminiert damit, dass ein Blatt gelöscht werden muss.

Damit die Färbungsregeln erfüllt sind, muss gewährleistet sein, dass das zu löschende Blatt immer rot ist.

§ Dies wird durch Farbwechsel und Rotationsoperationen erreicht, die beim iterativen top-Down-Durchlauf (ähnlich wie bei beim Einfügen) durchgeführt werden.

§ Näheres siehe in [Weiss 2011].

Referenzen

ÄHNLICHE DOKUMENTE

Die „nachher“-Position bezieht sich immer auf den den neuen Wurzelknoten, der Pfad zu dem entsprechenden Knoten beginnt immer beim alten Wurzelknoten k...  Ausgleichen  durch

[r]

Ein zufällig erzeugter BST mit n Elementen ist ein BST, der durch das Einfügen von n Schlüsseln in zufälliger Reihenfolge in einen anfangs leeren Baum entsteht. Annahme: Jede

I Färben wir ihn aber rot, dann könnten wir die Farbbedingungen verletzen (rote Knoten haben keine roten Kinder). Wir färben den Knoten daher rot (eine Schwarz-Höhen-Verletzung

Der Nachfolger ist der jüngste Vorfahre, dessen linker Teilbaum node enthält.

Bedeutung von Reduktionsfaktoren (Prinzip, keine Formeln!) Anwendung algebraischer Äquivalenzen.. Vergleich kostenbasierte

• Jeder Schlüssel im linken Teilbaum eines Knotens ist kleiner als der Schlüssel im Knoten selbst. • Jeder Schlüssel im rechten Teilbaum eines Knotens ist grösser als oder gleich

Entsteht nach dem Einfügen oder Entfernen eines Knotens ein unausgeglichener Knoten der Situation 1 oder 2, kann dieser Knoten durch eine einfache Rotation wieder ausgeglichen