(Operanden) und mathematischen Operatoren soll - oth

Werbung
Algorithmen und Datenstrukturen
Fachhochschule Regensburg
Algorithmen und Datenstrukturen
AVL-Bäume 1
9. Übungsblatt
Algorithmen und Datenstrukturen
Name: ________________________
Lehrbeauftragter: Prof. Sauer
Vorname: _____________________
Abb. 1: Darstellung eines AVL-Baums mit Balancierungsangeben (Höhendifferenzen) 2
1. Einfügen von Knoten im AVL-Baum 3
Ein binärer Suchbaum hat die AVL-Eigenschaft, wenn sich in jedem Knoten sich die Höhen der beiden
Teilbäume höchstens um 1 unterscheiden. Diese Last („Balance“) muß in einem Knoten gespeichert
sein. Es genügt aber als Maß für die Unsymmetrie eine Höhendifferenz festzuhalten, die nur die Werte
–1 (linkslastig), 0 (gleichlastig) und +1 (rechtslastig) annehmen kann. Die AVL-Eigenschaft ist verletzt,
wenn diese Höhendifferenz +2 bzw. –2 ist. Der Knoten, der diesen Wert erhalten hat, ist der Knoten
„alpha“, dessen Unausgeglichenheit auf einen der folgenden 4 Fälle zurückzuführen ist:
1. Einfügen in den linken Teilbaum, der vom linken Nachkommen des Knoten „alpha“ bestimmt ist.
2. Einfügen in den rechten Teilbaum, der vom linken Nachkommen des Knoten „alpha“ bestimmt ist.
3. Einfügen in den linken Teilbaum, der vom rechten Nachkommen des Knoten „alpha“ bestimmt ist.
4. Einfügen in den rechten Teilbaum, der vom rechten Nachkommen des Knoten „alpha“ bestimmt ist
Fall 1 und Fall 4 bzw. Fall 2 und Fall 3 sind Spiegelbilder, zeigen also das gleiche Verhalten.
Fall1 kann durch einfache Rotation behandelt werden und ist leicht zu bestimmen, daß das Einfügen
„außerhalb“ (links – links bzw. rechts – rechts im Fall 4) stattfindet.
Fall 2 kann durch doppelte Rotation behandelt werden und ist ebenfalls leicht zu bestimmen, da das
Einfügen „innerhalb“ (links –rechts bzw. rechts – links) erfolgt.
Die einfache Rotation
Die folgende Darstellung beschreibt den Fall 1 vor und nach der Rotation:
1
Vgl. Skriptum 4.3.2
vgl. AVLTreeTest.java, AVLTree.java
3 vgl. Skriptum, 4.3.2
2
1
Algorithmen und Datenstrukturen
k2
k1
k1
k2
Z
Y
X
Y
Z
X
Die folgende Darstellung beschreibt Fall 4 vor und nach der Rotation :
k1
k2
k2
k1
X
Y
X
Y
Z
Z
Doppelrotation
Die einfache Rotation führt in den Fällen 2 und 3 nicht zum Erfolg.
Fall 2 muß durch eine Doppelrotation (links – rechts) behandelt werden.
k3
k2
k1
k1
k3
D
k2
B
A
A
B
C
2
C
D
Algorithmen und Datenstrukturen
Auch Fall 3 muß durch Doppelrotation behandelt werden
k1
k3
k2
k1
k2
A
k3
D
B
A
B
C
D
C
Implementierung 4
Zum Einfügen eines Knoten mit dem Datenwert „x“ in einen AVL-Baum, wird „x“ rekursiv in den
betoffenen Teilbaum eingesetzt. Falls die Höhe dieses Teilbaums sich nicht verändert, ist das
Einfügen beendet. Liegt Unausgeglichenheit vor, dann ist einfache oder doppelte Rotation (abhängig
von „x“ und den Daten des betroffenen Teilbaums) nötig.
AVL-Baumknoten
Er enthält für jeden Knoten eine Angabe zur Höhe(ndifferenz) 5 seiner Teilbäume.
// Baumknoten fuer AVL-Baeume
class AvlKnoten
{
// Instanzvariable
protected AvlKnoten links;
// Linkes Kind
protected AvlKnoten rechts;
// Rechtes Kind
protected int
hoehe;
// Hoehe
public Comparable daten;
// Das Datenelement
// Konstruktoren
public AvlKnoten(Comparable datenElement)
{
this(datenElement, null, null );
}
public AvlKnoten( Comparable datenElement,
AvlKnoten lb,
AvlKnoten rb )
{
daten = datenElement;
links = lb;
rechts = rb;
hoehe = 0;
}
}
Der AVL-Baum
Bei jedem Schritt ist festzustellen, ob die Höhe des Teilnaums, in dem ein Element eingefügt wurde,
zugenommen hat.
/*
* Rueckgabe: Hoehe des Knotens, oder -1, falls null.
*/
4
5
im Verzeichnis ueb09 steht die aktuellen Version, /ueb/pr43210/GenAVLBaum.java
vgl. Skriptum, 4.3.3
3
Algorithmen und Datenstrukturen
private static int hoehe(AvlKnoten b)
{
return b == null ? -1 : b.hoehe;
}
Die Methode „insert“ führt das Einfügen eines Baumknoten in den Avl-Baum aus:
/*
* Interne Methode zum Einfuegen eines Baumknoten in einen Teilbaum.
* x ist das einzufuegende Datenelement.
* b ist der jeweilige Wurzelknoten.
* Rueckgabe der neuen Wurzel des jeweiligen Teilbaums.
*/
private AvlKnoten insert(Comparable x, AvlKnoten b)
{
if( b == null )
b = new AvlKnoten(x, null, null);
else if (x.compareTo( b.daten) < 0 )
{
b.links = insert(x, b.links );
if (hoehe( b.links ) - hoehe( b.rechts ) == 2 )
if (x.compareTo( b.links.daten ) < 0 )
b = rotationMitLinksNachf(b);
else
b = doppelrotationMitLinksNachf(b);
}
else if (x.compareTo( b.daten ) > 0 )
{
b.rechts = insert(x, b.rechts);
if( hoehe(b.rechts) - hoehe(b.links) == 2)
if( x.compareTo(b.rechts.daten) > 0 )
b = rotationMitRechtsNachf(b);
else
b = doppelrotationMitRechtsNachf( b );
}
else
; // Duplikat; tue nichts
b.hoehe = max( hoehe( b.links ), hoehe( b.rechts ) ) + 1;
return b;
}
Einfache Rotation
RotationMitLinksNachf dreht den Linken Teilbaum der folgenden Darstellung nach rechts.
k2
k1
k1
k2
Z
Y
X
Y
Z
X
/*
* Rotation Binaerbaumknoten mit linkem Nachfolger.
* Fuer AVL-Baeume ist dies eine einfache Rotation (Fall 1).
4
Algorithmen und Datenstrukturen
* Aktualisiert Angaben zur Hoehe, dann Rueckgabe der neuen Wurzel.
*/
private static AvlKnoten rotationMitLinksNachf(AvlKnoten k2)
{
AvlKnoten k1 = k2.links;
k2.links = k1.rechts;
k1.rechts = k2;
k2.hoehe = max( hoehe( k2.links ), hoehe( k2.rechts ) ) + 1;
k1.hoehe = max( hoehe( k1.links ), k2.hoehe ) + 1;
return k1;
}
Doppelrotation
“doppelrotationMitLinksNachf” führt die folgende Umstellung der Baumknoten aus:
k3
k2
k1
k1
k3
D
k2
B
A
C
A
B
D
C
/*
* Doppelrotation Fall 2: erstes linkes Kind mit seinem rechten Kind;
* dann Knoten k3 mit neuem linken Kind.
* Aktualisieren der Hoehen,
* dann Rueckgabe der neuen Wurzel.
*/
private static AvlKnoten doppelrotationMitLinksNachf(AvlKnoten k3)
{
k3.links = rotationMitRechtsNachf( k3.links );
return rotationMitLinksNachf( k3 );
}
2. Löschen von Knoten im AVL-Baum
Das Löschen eines Knotens (Schlüssel x) mit 2 Kindern kann auf das Löschen von Blatt-/Randknoten
zurückgeführt werden. Für innere Knoten gilt:
-
„x“ wird ersetzt durch den kleinsten Schlüssel y im rechten Teilbaum von x (bzw. größten
Schlüssel im linken Teilbaum).
Führt zur Änderung des Balancierungsfaktors für v (Höhe des linken Teilbaums von v hat sich
um 1 reduziert).
5
Algorithmen und Datenstrukturen
x
y
⇒
v
v
Bl
Bl
z
y
Bry
Br
Br
Bry
z
Bis auf Symmetrie treten nur 3 Fälle auf.
Fall 1:
0
v
h+1
1
h+1
Löschen in Bl
⇒
h
h
h-1
Bl
h
Br
Bl
Br
In diesem Fall pflanzt sich Höhenerniedrigung nicht fort, da in der Wurzel das AVL-Kriterium erfüllt
bleibt, d.h. kein Rebalancieren erforderlich.
Fall 2:
-1
h+1
0
h
Löschen in Bl
⇒
h
h-1
Bl
h-1
Br
Bl
Br
h-1
Die Höhenerniedrigung von Bl pflanzt sich hier zur Wurzel fort. Sie kann auf diesem Pfad eine
Rebalancierung auslösen.
Fall 3:
6
Algorithmen und Datenstrukturen
-1
h+1
-2
Löschen in
⇒
h
Br
h-1
h
Br
Bl
h+1
h-2
Br
Bl
Für die Behandlung dieser Situation ist der linke Teilbaum Bl genauer zu betrachten. Dabei ergeben
sich 3 Unterfälle:
Fall 3a:
-2
x4
1
x2
h+1
h+1
⇒
0
x2
-1
x4
B5
B
h-2
h-1
B1
h-1
h-1
B1
h-1
B3
0
x2
h
h-2
B5
h-2
B5
B3
- Rechtsrotation führt zur Erfüllung des AVL-Kriteriums
- Teilbaum behält ursprüngliche Höhe
- Keine weiteren Rebalancierungen erforderlich
Fall 3b:
-2
x4
h+1
⇒
-1
x2
0
x4
B5
B
h-2
h-1
B1
h-1
h-2
B1
h-2
B3
B3
- Rechtsrotation reduziert Höhe des gesamten Teilbaum von h+1 nach h
- Höhenreduzierung pflanzt sich auf dem Pfad zur Wurzel hin fort und kann zu weiteren
Rebalancierungen führen.
7
Algorithmen und Datenstrukturen
-2 h+1
x6
+1
x2
0
x4
h
h
h-2
B7
0
x2
B
0
x4
0
x6
h-2
h-2
B1
B3
B5
B7
B1
h-2
h-2
B3
B5
B
- Doppelrotation
- ggf. fortgesetzte Rebalancierungen
Rebalancierungsschritte beim Löschen
1. Suche im Löschpfad nähesten Vater mit Balancierungsfaktor +/-2
2. Führe ggf. Rotation im gegenüberliegenden Teilbaum dieses Vaters auf. Im Gegensatz zum
Einfügevorgang kann hier eine Rotation wiederum auf dem Pfad zur Wurzel auslösen, da sie
in gewissen Fällen auf eine Höhenerniedrigung des transformierten Teilbaums führt. Die
Anzahl der Rebalancierungsschritte ist jedoch durch die Höhe h des Baums begrenzt.
Höhe von AVL-Bäumen
Balancierte Bäume werden als Kompromiß zwischen ausgeglichenen und natürlichen Suchbäumen
eingeführt, wobei „logarithmischer Suchaufwand“ im schlechtesten Fall gefordert wurde. Für die
h +1
maximale Anzahl von Knoten n gilt folgende Ungleichung: n ≤ 2
− 1 . Daraus erhält man zur
h ≤ 2 ⋅ log 2 n + 1 . Das bedeutet, dass die Höhe eines AVL-Baums von der
Wurzel bis zu einem beliebigen Knoten höchstens 2 ⋅ log 2 n + 1 ist
Abschätzung der Höhe:
Komplexität von Opeartionen aujf AVL-Bäumen
- Komplexität für Einfügen und Löschen in binären Suchbäumen: O (h) .
-- im AVL- Baum gilt: h = O (log n)
-- Notwendige Rotationen sind in konstanter Zeit auszuführen
- Ausbalancieren nach Einfügen erfordert höchstens eine (einfache oder doppelte) Rotation.
Komplexität von insert: O (log n) + O (1) = O (log n)
- Ausbalancieren nach Löschen erfordert höchstens h (einfache und doppelte) Rotationen.
Komplexität von remove: O (log n) + O (log n) = O (log n)
- Einfügen und Löschen in AVL-Bäumen haben im schlechtesten Fall eine Komplexität von O(logn)
- Zusammenfassung: worst-case Komplexität O (log n ) für Suchen, Einfügen und Löschen.
8
Herunterladen