Microsoft PowerPoint - 05 B\344ume 2 - informatik.uni

Werbung
Universität Bremen
Bäume 2
Thomas Röfer
Suchbäume
Suchen, Einfügen, Löschen
Balancierte Bäume (AVL-Bäume)
B-Bäume
Universität Bremen
Rückblick „Bäume 1“
Begriffe
Durchlaufen von Bäumen
Spielprobleme
Huffman-Baum
1
Eigene Züge
Eigene Züge
9
0
1 5
0
0
1 2 0 1 2 01 2 0 3
1 1 1 1 1 1 B
H
PI-2: Bäume 2
4
1
Eigene Züge
Gegnerische Züge
9
1
Gegnerische Züge
0
18
G
F
2
E
D
C
A
Universität Bremen
Suchbäume
Motivation
Ein Suchbaum dient zum schnellen
Auffinden von Werten, möglichst in O(log n)
Definition
Die Schlüssel aller linken Nachfolger sind
kleiner als der Schlüssel eines Knotens, die
Schlüssel aller rechten sind größer (oder
gleich)
Ein natürlicher Baum wird durch zufälliges
Einfügen von Schlüsseln erzeugt und ist
nicht notwendigerweise balanciert
27 … 39 39 … ∞
Alternative Schreibweise
((( 1 ) 3 (( 14 ) 15 )) 27 ( 39 ))
-∞ … 1
1…3
15 … 27
Sichtweise
Die Blätter repräsentieren Intervalle im
Wertebereich der Schlüssel
PI-2: Bäume 2
3 … 14
14 … 15
3
Universität Bremen
Normaler Suchbaum
Ansatz
Werte stehen in inneren Knoten
Blätter sind leer
Suchalgorithmus
Fall 1: Knoten ist innerer Knoten
Falls Schlüssel gleich gesuchtem
Wert, dann gefunden
Ansonsten abhängig von Vergleich
zwischen Wert und Schlüssel links
oder rechts weitersuchen
Fall 2: Knoten ist Blatt
nicht gefunden
Wert
Aufwand
O(Höhe des Baumes)
PI-2: Bäume 2
4
Universität Bremen
Blattsuchbäume
Ansatz
Geordnet wie Suchbäume
Werte stehen in Blättern
Innere Knoten enthalten nur
„Wegweiser“
z.B. größten Wert des linken Teilbaums
Suchalgorithmus
Fall 1: Knoten ist innerer Knoten
Abhängig von Vergleich zwischen Wert
und Wegweiser links oder rechts
weitersuchen
Fall 2: Knoten ist Blatt
Wenn Wert gleich Schlüssel, dann
gefunden
Ansonsten nicht gefunden
PI-2: Bäume 2
5
Universität Bremen
Suchen in Suchbaum
Wenn gesuchter Wert
gleich dem Schlüssel
gefunden
kleiner als Schlüssel
weitersuchen in linkem Nachfolger
ansonsten
weitersuchen in
rechtem Nachfolger
PI-2: Bäume 2
Comparable
Comparable search(Comparable
search(Comparable value)
value)
{{
return
return search2(root,
search2(root, value);
value);
}}
private
private Comparable
Comparable search2(
search2(
Node
node,
Comparable
Node node, Comparable value)
value)
{{
if(node
if(node ==
== null)
null)
return
null;
return null;
else
else
{{
int
int cc == value.compareTo(node.data);
value.compareTo(node.data);
if(c
if(c << 0)
0)
return
return search2(node.left,
search2(node.left, value);
value);
else
if(c
>
0)
else if(c > 0)
return
return search2(node.right,
search2(node.right, value);
value);
else
else
return
return node.data;
node.data;
}}
}}
6
Universität Bremen
Suchbaum mit Wächter/Stopper
Ansatz
Wie beim Suchen in Listen/Arrays mit
Wächter/Stopper
Test auf „nicht gefunden“ entfällt, da
Wert garantiert gefunden wird
Könnte in Java auch durch
Ausnahmebehandlung ersetzt
werden
Implementierung
In einem Suchbaum sind alle Blätter
identisch (ist somit eigentlich kein
Baum mehr)
In dieses einzige Blatt wird der
gesuchte Wert geschrieben
PI-2: Bäume 2
7
Universität Bremen
Einfügen in einen Suchbaum
insert(17)
PI-2: Bäume 2
8
Universität Bremen
Einfügen in einen Suchbaum
Algorithmus
Suche nach dem einzufügenden
Wert, wobei selbst dann
weitergesucht wird, wenn er
gefunden wurde
Es sei denn, man will jeden Wert
nur einmal im Suchbaum
repräsentieren
Dadurch wird auf jeden Fall ein
externer Knoten gefunden
Dieser wird durch ein neues Blatt
mit dem einzufügenden Wert
ersetzt
PI-2: Bäume 2
void
void insert(Comparable
insert(Comparable value)
value)
{{
if(root
if(root ==
== null)
null)
new
root
=
root = new Node(value);
Node(value);
else
else
insert2(root,
insert2(root, value);
value);
}}
private
private void
void insert2(Node
insert2(Node node,
node,
Comparable
Comparable value)
value)
{{
if(value.compareTo(node.data)
if(value.compareTo(node.data) << 0)
0)
if(node.left
==
null)
if(node.left == null)
node.left
node.left == new
new Node(value);
Node(value);
else
else
insert2(node.left,
insert2(node.left, value);
value);
else
else
if(node.right
if(node.right ==
== null)
null)
node.right
node.right == new
new Node(value);
Node(value);
else
else
insert2(node.right,
insert2(node.right, value);
value);
}}
9
Universität Bremen
Löschen aus einem Suchbaum
8
4
2
1
5
1×
n×
3
8
5
6
2
7
1
6
3
7
remove(4)
PI-2: Bäume 2
10
Universität Bremen
Löschen aus einem Suchbaum
Suche den zu löschenden
Knoten
Merke unterwegs jeweils den
Elternknoten
Wenn er gefunden wurde
Falls einer seiner Nachfolger leer
ist, ersetze ihn in seinem
Elternknoten durch den jeweils
anderen Nachfolger
Ansonsten suche den Knoten k mit
dem nächst größeren Wert,
überschreibe im zu löschenden
Knoten den Wert mit dem Wert
von k und lösche danach k
PI-2: Bäume 2
void
void remove(Comparable
remove(Comparable value)
value)
{{
remove2(root,
remove2(root, null,
null, value);
value);
}}
private
private void
void remove2(Node
remove2(Node node,
node,
Node
parent,
Node parent,
Comparable
Comparable value)
value)
{{
if(node
if(node !=
!= null)
null)
{{
int
int cc == value.compareTo(node.data);
value.compareTo(node.data);
if(c
<
0)
if(c < 0)
remove2(node.left,
remove2(node.left, node,
node, value);
value);
else
else if(c
if(c >> 0)
0)
remove2(node.right,
remove2(node.right, node,
node, value);
value);
else
else
removeNode(node,
removeNode(node, parent);
parent);
}}
}}
11
Universität Bremen
Löschen aus einem Suchbaum
private
private void
void removeNode(Node
removeNode(Node node,
node,
Node
parent)
Node parent)
{{
if(node.right
if(node.right ==
== null)
null)
replaceChild(parent,
replaceChild(parent, node,
node,
node.left);
node.left);
else
else if(node.left
if(node.left ==
== null)
null)
replaceChild(parent,
replaceChild(parent, node,
node,
node.right);
node.right);
else
else if(node.right.left
if(node.right.left ==
== null)
null)
{{
node.right.left
node.right.left == node.left;
node.left;
replaceChild(parent,
replaceChild(parent, node,
node,
node.right);
node.right);
}}
else
else
{{
Node
Node pon
pon == getParentOfNext(node);
getParentOfNext(node);
node.data
node.data == pon.left.data;
pon.left.data;
pon.left
=
pon.left.right;
pon.left = pon.left.right;
}}
}}
PI-2: Bäume 2
private
private void
void replaceChild(Node
replaceChild(Node node,
node,
Node
oldNode,
Node
newNode)
Node oldNode, Node newNode)
{{
if(node
if(node ==
== null)
null)
root
=
newNode;
root = newNode;
else
else if(node.left
if(node.left ==
== oldNode)
oldNode)
node.left
=
newNode;
node.left = newNode;
else
else
node.right
node.right == newNode;
newNode;
}}
private
private Node
Node getParentOfNext(Node
getParentOfNext(Node node)
node)
{{
node
node == node.right;
node.right;
while(node.left.left
while(node.left.left !=
!= null)
null)
node
=
node.left;
node = node.left;
return
return node;
node;
}}
12
Universität Bremen
Balancierte Bäume
Motivation
Durch degenerierte Bäume kann die Suchdauer stark
ansteigen
AVL-Baum (Adelson-Velskij und Landis)
Definition
Ein Baum ist AVL-ausgeglichen oder höhenbalanciert,
wenn für jeden Knoten des Baumes gilt, dass sich die
Höhe seines linken Teilbaums von der des rechten
Teilbaums um maximal 1 unterscheidet
Algorithmus-Idee
Jedes Einfügen oder Löschen kann die Balanciertheit des
Baumes zerstören.
Daher wird der Baum jeweils rebalanciert, sobald die
Höhen des linken und rechten Teilbaums um zwei
auseinander liegen
PI-2: Bäume 2
13
Universität Bremen
Balanciertheit, Höhe, Rotieren
Baum
x
Leerer Baum:
Sonst: (t1, x, t2)
t1
Balanciertheit
t2
heightbal( )
= true
heightbal((t1, x, t2)) = | height(t1) - height(t2) | ≤ 1 /\ heightbal(t1) /\ heightbal(t2)
Höhe
height( )
=0
height((t1, x, t2)) = max(height(t1), height(t2)) + 1
Baum rotieren
rotr(((t1, y, t2), x, t3)) = (t1, y, (t2, x, t3))
rotl((t1, y, (t2, x, t3))) = ((t1, y, t2), x, t3)
y
t1
rotr
x
t3
t1
t2
PI-2: Bäume 2
x
t2
rotl
f((t1, x, t2)) = (t2, x, t1)
Node f(Node n) {
return new Node(n.right, n.data, n.left);}
y
14
t3
Universität Bremen
Einfügen in AVL-Baum
Einfügen
insert(x, ) = ( , x, )
insert(x, (t1, y, t2)) =
rebal((insert(x, t1), y, t2))
falls x < y
rebal((t1, y, insert(x, t2)))
sonst
Neigung eines Knotens
slope( )
slope((t1, x, t2))
Kann im Baum gespeichert werden und braucht
nicht immer wieder neu ausgerechnet zu werden
Rebalancieren
rebal(t) =
PI-2: Bäume 2
shiftr(t)
shiftl(t)
t
+
=0
= height(t1) - height(t2)
-
+
-1
falls slope(t) = 2
falls slope(t) = -2
sonst
15
Universität Bremen
(Doppel-)Rotieren in AVL-Baum
rotr((rotl(t1), x, t2)) falls slope(t1) = -1
shiftr((t1, x, t2)) =
rotr((t1, x, t2))
x 2
t1
t3
y 0, 1
t2
y
0
t4
t2
PI-2: Bäume 2
t1
y
-1
y 1, 0
t2
z
t3
t4
rotr((t1, x, t2))
shiftl((t1, x, t2)) =
z 0
x 2
x 1, 0
t3
t4
sonst
t3
t5
rotr((rotl(t1), x, t2))
rotl((t1, x, rotr(t2))) falls slope(t2) = 1
rotl((t1, x, t2))
t4
sonst
16
x 0, -1
t5
t2
Universität Bremen
Löschen aus einem AVL-Baum
Löschen
remove(x, ) =
remove(x, (t1, x, )) = t1
remove(x, ( , x, t2)) = t2
remove(x, (t1, x, t2)) = rebal(t1, y, t)
wobei (y, t) = leftest(t2)
remove(x, (t1, y, t2)) = rebal((remove(x, t1), y, t2)) falls x < y
remove(x, (t1, y, t2)) = rebal((t1, y, remove(x, t2))) falls x ≥ y
8
4
1×
2
n×
1
3
6
5
7
Finden des nächsten Elements
leftest(( , x, t)) = (x, t)
leftest((t1, x, t2)) = (y, rebal((t, x, t2)))
wobei (y, t) = leftest(t1)
Aufwand
8
5
2
6
Rebalancieren eines Knotens passiert in konstanter Zeit
Bei Einfügen und Löschen wird auf dem Pfad von der
1
3
Wurzel zu einem Knoten pro Knoten einmal rebalanciert
Also ist der Aufwand O(Höhe des Baumes)
Da der Baum balanciert ist, ist der Aufwand also O(log n), auch im schlechtesten Fall
PI-2: Bäume 2
17
7
Universität Bremen
B-Bäume
Motivation
AVL-Bäume eignen sich nicht gut für die Verwaltung von Daten auf Massenspeichern
(Festplatten)
Auf Daten auf Festplatten wird in Form von Sektoren zugegriffen
Der Wechsel zwischen Sektoren kostet Zeit (Kopfbewegung)
Daher: Daten linear, Baumstruktur als Index (ein Blattsuchbaum)
Index ist auch ein Baum, aber ein B-Baum, bei dem ein Knoten in einen Sektor passt
B-Baum der Ordnung m
Alle Blätter habe die gleiche Tiefe
Jeder Knoten mit Ausnahme der Wurzel und
der Blätter hat wenigstens m/2 Kinder
Die Wurzel hat mindestens 2 Kinder
Jeder Knoten hat höchstens m Kinder
Jeder Knoten mit i Kindern hat i-1 Schlüssel
PI-2: Bäume 2
18
Universität Bremen
Einfügen und Suchen in B-Baum
Suchen
Binäre Suche in den Schlüsseln eines Knotens
Dann zum nächsten Knoten, so lange, bis Blatt erreicht
Einfügen
Suche nach Einfügeposition (ein Blatt)
Fall 1: Übergeordneter Knoten ist noch nicht voll
Füge Schlüssel in Knoten ein
Erzeuge neues Blatt und referenziere dieses aus dem Knoten
insert(x)
PI-2: Bäume 2
19
Universität Bremen
Einfügen in einen B-Baum
Fall 2: Übergeordneter Knoten
ist voll
Füge Schlüssel in Knoten ein (ist zu
groß)
Teile Knoten in der Mitte
Füge mittleren Knoten dem
Elternknoten hinzu
Falls dieser zu voll ist, teile ihn auch
Falls die Wurzel geteilt wird, schaffe
eine neue Wurzel und hänge die
beiden Hälften der alten Wurzel als
Nachfolger daran
PI-2: Bäume 2
20
Universität Bremen
Beispiel: Einfügen in B-Baum
insert(14)
PI-2: Bäume 2
21
Herunterladen