ueb8

Werbung
Algorithmen und Datenstrukturen
Übung 8: Splay-Bäume
Zugrunde liegende Idee
Nachdem auf einen Baumknoten zugegriffen wurde, wird dieser Knoten über eine Reihe von AVLRotationen zur Wurzel. Bis zu einem gewissen Grade führt das zur Ausbalancierung.
Bsp.:
1.
x
y
x
y
C
A
A
B
B
2.
e
C
e
d
e
d
F
c
d
F
c
b
F
a
a
E
E
E
c
a
A
b
b
A
D
B
A
B
C
C
B
D
C
e
D
a
a
e
c
F
c
d
d
F
A
b
A
b
E
B
C
B
D
C
1
E
D
Algorithmen und Datenstrukturen
Splaying-Operationen
Der Knoten „x“ im Splay-Baum bewegt sich über einfache und doppelte Rotationen zur Wurzel. Man
unterscheidet folgende Fälle
1. (zig): x ist ein Kind der Wurzel von einem Splay-Baum, einfache Rotation
2. (zig-zig): x hat den Großvater g(x) und den Vater p(x), x und p(x) sind jeweils linke (bzw. rechte)
Kinder ihres Vaters.
g(x)
g(x) = p(y)
bzw.
p(x)
y = p(x)
A
D
x
x
B
C
C
A
D
B
x
y
z
A
B
C
D
3. (zig-zag): x hat Großvater g(x) und Vater p(x), x ist linkes (rechtes) Kind von p(x), p(x) ist rechtes
(linkes) Kind von g(x)
z = g(x)
x
y = p(x)
D
y
z
x
A
A
B
C
2
B
C
D
Algorithmen und Datenstrukturen
Implementierung1
BinaerBaumKnoten
// Elementarer Knoten eines binaeren Baums, der nicht ausgeglichen ist
// Der Zugriff auf diese Klasse ist nur innerhalb eines Verzeichnisses
// bzw. Pakets moeglich
class BinaerBaumknoten
{
// Instanzvariable
protected BinaerBaumknoten links;
// linker Teilbaum
protected BinaerBaumknoten rechts;
// rechter Teilbaum
public Comparable daten;
// Dateninhalt der Knoten
// Konstruktor
public BinaerBaumknoten(Comparable datenElement)
{
this(datenElement, null, null );
}
public BinaerBaumknoten(Comparable datenElement,
BinaerBaumknoten l,
BinaerBaumknoten r)
{
daten
= datenElement;
links
= l;
rechts
= r;
}
public void insert (Comparable x)
{
if (x.compareTo(daten) > 0)
// dann rechts
{
if (rechts == null) rechts = new BinaerBaumknoten(x);
else rechts.insert(x);
}
else // sonst links
{
if (links == null) links = new BinaerBaumknoten(x);
else links.insert(x);
}
}
public BinaerBaumknoten getLinks()
{
return links;
}
public BinaerBaumknoten getRechts()
{
return rechts;
}
}
SplayBaum
//
//
//
//
//
//
//
//
1
SplayBaum class
KONSTRUCTION: ohne Initialisierer
***************** PUBLIC OPERATIONen ********************
void insert( x )
--> Insert x
void remove( x )
--> Remove x
Comparable find( x )
--> Return item that matches x
pr43215
3
Algorithmen und Datenstrukturen
//
//
//
//
//
Comparable findMin( )
Comparable findMax( )
boolean isEmpty( )
void makeEmpty( )
void printTree( )
-->
-->
-->
-->
-->
Return smallest item
Return largest item
Return true if empty; else false
Remove all items
Print tree in sorted order
/*
* Implementiere einen top-down Splay Baum.
* Vergleiche beziehen sich auf die Methode compareTo.
*/
public class SplayBaum
{
private BinaerBaumknoten root;
private static BinaerBaumknoten nullNode;
static
// Static initializer for nullNode
{
nullNode = new BinaerBaumknoten( null );
nullNode.links = nullNode.rechts = nullNode;
}
private static BinaerBaumknoten newNode = null;
// wird in diversen Einfuegevorgaengen benutzt
private static BinaerBaumknoten header = new BinaerBaumknoten(null);
/*
* Konstruktor.
*/
public SplayBaum( )
{
root = nullNode;
}
/*
* Zugriff auf die Wurzel
*/
public BinaerBaumknoten holeWurzel()
{
return root;
}
/*
* Insert.
* Parameter x ist das einzufuegende Element.
*/
public void insert( Comparable x )
{
if( newNode == null )
newNode = new BinaerBaumknoten( null );
newNode.daten = x;
if( root == nullNode )
{
newNode.links = newNode.rechts = nullNode;
root = newNode;
}
else
{
root = splay( x, root );
if( x.compareTo( root.daten ) < 0 )
{
newNode.links = root.links;
newNode.rechts = root;
root.links = nullNode;
root = newNode;
}
else if( x.compareTo( root.daten ) > 0 )
{
newNode.rechts = root.rechts;
4
Algorithmen und Datenstrukturen
newNode.links = root;
root.rechts = nullNode;
root = newNode;
}
else return;
}
newNode = null;
// So next insert will call new
}
/*
* Remove.
* Parameter x ist das zu entfernende Element.
*/
public void remove( Comparable x )
{
BinaerBaumknoten neuerBaum;
// Falls x gefunden wird, liegt x in der Wurzel
root = splay( x, root );
if( root.daten.compareTo( x ) != 0 )
return;
// Element nicht gefunden; tue nichts
if( root.links == nullNode )
neuerBaum = root.rechts;
else
{
// Finde das Maximum im linken Teilbaum
// Splay it to the root; and then attach right child
neuerBaum = root.links;
neuerBaum = splay( x, neuerBaum );
neuerBaum.rechts = root.rechts;
}
root = neuerBaum;
}
/*
* Bestimme das kleinste Daten-Element im Baum.
* Rueckgabe: kleinstes Datenelement bzw. null, falls leer.
*/
public Comparable findMin( )
{
if( isEmpty( ) ) return null;
BinaerBaumknoten ptr = root;
while( ptr.links != nullNode ) ptr = ptr.links;
root = splay( ptr.daten, root );
return ptr.daten;
}
/*
* Bestiime das groesste Datenelement im Baum.
* Rueckgabe: das groesste Datenelement bzw. null, falls leer
*/
public Comparable findMax( )
{
if (isEmpty( )) return null;
BinaerBaumknoten ptr = root;
while( ptr.rechts != nullNode ) ptr = ptr.rechts;
root = splay( ptr.daten, root );
return ptr.daten;
}
/*
* Bestimme ein datenelement im Baum.
* Parameter x entfält das zu suchende Element.
* Rueckgabe: Das passende Datenelement oder null, falls leer
*/
public Comparable find( Comparable x )
{
root = splay( x, root );
5
Algorithmen und Datenstrukturen
if (root.daten.compareTo( x ) != 0) return null;
return root.daten;
}
/*
* Mache den Baum logisch leer.
*/
public void makeEmpty( )
{
root = nullNode;
}
/*
* Ueberpruefe, ob der Baum logisch leer ist if the tree is logically
empty.
* Rueckgabe true, falls leer, anderenfalls false.
*/
public boolean isEmpty( )
{
return root == nullNode;
}
/*
* Gib den Inhalt des baums in sortierter Folge aus.
*/
public void printTree( )
{
if (isEmpty( ))
System.out.println( "Empty tree" );
else
printTree( root );
}
/*
* Ausgabe des Binaerbaums um 90 Grad versetzt
*/
public void ausgBinaerbaum(BinaerBaumknoten b, int stufe)
{
if (b != b.links)
{
ausgBinaerbaum(b.links,stufe + 3);
for (int i = 0; i < stufe; i++)
{
System.out.print(' ');
}
System.out.println(b.daten.toString());
ausgBinaerbaum(b.rechts,stufe + 3);
}
}
/*
* Interne Methode zur Ausfuehrung eines "top down" splay.
* Der zuletzt im Zugriff befindliche Knoten
* wird die neue Wurzel.
* Parameter x Ist das Zielelement, die Umgebung fuer das Splaying.
* Parameter b ist die Wurzel des Teilbaums,
* um den das Splaying stattfindet.
* Rueckgabe des Teilbaums.
*/
private BinaerBaumknoten splay( Comparable x, BinaerBaumknoten t )
{
BinaerBaumknoten leftTreeMax, rightTreeMin;
header.links = header.rechts = nullNode;
leftTreeMax = rightTreeMin = header;
nullNode.daten = x;
// Guarantee a match
for( ; ; )
if( x.compareTo( t.daten ) < 0 )
{
6
Algorithmen und Datenstrukturen
if( x.compareTo( t.links.daten ) < 0 )
t = rotateWithLeftChild( t );
if( t.links == nullNode ) break;
// Kette Rechts
rightTreeMin.links = t;
rightTreeMin = t;
t = t.links;
}
else if( x.compareTo( t.daten ) > 0 )
{
if( x.compareTo( t.rechts.daten ) > 0 )
t = rotateWithRightChild( t );
if( t.rechts == nullNode ) break;
// Kette Links
leftTreeMax.rechts = t;
leftTreeMax = t;
t = t.rechts;
}
else break;
leftTreeMax.rechts = t.links;
rightTreeMin.links = t.rechts;
t.links = header.rechts;
t.rechts = header.links;
return t;
}
/*
* Rotation BinaerBaumknoten mit linkem Nachfolger.
*/
static BinaerBaumknoten rotateWithLeftChild(BinaerBaumknoten k2)
{
BinaerBaumknoten k1 = k2.links;
k2.links = k1.rechts;
k1.rechts = k2;
return k1;
}
/*
* Rotation BinaerBaumknoten mit rechtem Nachfolger.
*/
static BinaerBaumknoten rotateWithRightChild(BinaerBaumknoten k1)
{
BinaerBaumknoten k2 = k1.rechts;
k1.rechts = k2.links;
k2.links = k1;
return k2;
}
/*
* Interne Methode zur Ausgabe eines Teilbaums in sortierter Folge.
* Parameter b ist der jweilige Wurzelknoten.
*/
private void printTree( BinaerBaumknoten b )
{
if( b != b.links )
{
printTree(b.links);
System.out.println(b.daten.toString( ));
printTree(b.rechts);
}
}
}
SplaybaumTest
import java.io.*;
7
Algorithmen und Datenstrukturen
public class SplayBaumTest
{
public static void main( String [ ] args )
{
SplayBaum b = new SplayBaum();
String eingabeZeile
= null;
System.out.println("Einfuegen");
BufferedReader eingabe = null;
eingabe = new BufferedReader(
new InputStreamReader(System.in));
try {
int zahl;
do
{
System.out.println("Zahl? ");
eingabeZeile = eingabe.readLine();
try {
zahl = Integer.parseInt(eingabeZeile);
b.insert(new Integer(zahl));
b.ausgBinaerbaum(b.holeWurzel(),2);
}
catch (NumberFormatException ne)
{ break; }
} while (eingabeZeile != "");
}
catch (IOException ioe)
{
System.out.println("Eingefangen in main()");
}
System.out.println("Loeschen");
try {
int zahl;
do
{
System.out.println("Zahl? ");
eingabeZeile = eingabe.readLine();
try {
zahl = Integer.parseInt(eingabeZeile);
b.remove(new Integer(zahl));
b.ausgBinaerbaum(b.holeWurzel(),2);
}
catch (NumberFormatException ne)
{ break; }
} while (eingabeZeile != "");
}
catch (IOException ioe)
{
System.out.println("Eingefangen in main()");
}
System.out.println("Zugriff auf das kleinste Element");
b.findMin();
b.ausgBinaerbaum(b.holeWurzel(),2);
System.out.println("Zugriff auf das groesste Element");
b.findMax();
b.ausgBinaerbaum(b.holeWurzel(),2);
}
}
8
Herunterladen