Beispiel

Werbung
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Übersicht
5.3 Subtypen und Vererbung
Klassifikationen und Typisierung
Typ beschreibt Eigenschaften von Objekten bzw. Werten.
• Klassifikationen und Typisierung
Annahme bisher:
Kein Objekt bzw. Wert gehört zu mehr als einem
(nicht-parametrisierten) Typ.
• Schnittstellentypen in Java
• Subtypbildung in Java
Ansatz:
• Dynamische Methodenauswahl
• Realisiere jede Klasse/jeden Begriff einer Klassifikation im
• Weitere Aspekte der Subtypbildung
• Führe partielle Ordnung ≤ (vgl. F. 531) auf Typen ein, so dass
- speziellere Typen gemäß der Ordnung kleiner als ihre
allgemeineren Typen sind und
- Objekte speziellerer Typen auch zu den allgemeineren gehören.
Programm durch einen Typ.
• Programmieren mit Schnittstellentypen
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1165
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Klassifikationen und Typisierung (2)
Beispiel: (Subtypbeziehungen)
Wenn S ≤ T gilt, d.h. wenn S ein Subtyp von T ist, dann gehören alle
Objekte von S auch zu T .
In Java gibt es einen allgemeinsten Referenztyp, genannt Object.
Wenn S ≤ T und S , T , heißt S ein echter Subtyp von T , in Zeichen
S < T.
Es gilt:
String ≤ Object,
MemoFrame ≤ Object, MemoFrame ≤ Frame,
Wenn S ≤ T , dann heißt T ein Supertyp von S, und wir schreiben
auch T ≥ S.
int[] ≤ Object,
Student ≤ Person, Person ≤ Object
Wenn S < T und es kein U mit S < U < T gibt, dann heißt S ein
direkter Subtyp von T .
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1166
1167
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1168
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Substituierbarkeit
5.3 Subtypen und Vererbung
Beispiel: (Substituierbarkeit)
Prinzip der Substituierbarkeit:
Sei S ≤ T ; dann ist an allen Programmstellen, an
denen ein Objekt vom Typ T zulässig ist, auch ein
Objekt vom Typ S zulässig.
Folgende Anweisungen sind typkorrektes Java:
Object ov
Konsequenzen:
• Subtypobjekte müssen alle Eigenschaften des Supertyps
aufweisen.
= "Ein String ist auch ein Object ";
Person [] p =
new Person [4];
p[0]
new Student (...);
=
• Eine Ausdruck von einem Subtyp kann an Stellen verwendet
werden, an denen in Sprachen ohne Subtypen nur ein Ausdruck
von einem allgemeineren Typ zulässig wäre.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1169
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Bemerkung:
1170
5.3 Subtypen und Vererbung
Referenztypen in Java
In Java gibt es zwei zentrale Arten von benutzerdefinierten Typen:
• Vereinfachend betrachtet, kann man Typen als die Menge ihrer
Objekte bzw. Werte auffassen.
• Klassentypen
Bezeichne M(S) die Menge der Objekte vom Typ S.
• Schnittstellentypen
Für Typen S und T gilt dann:
Darüber hinaus gibt es die zugehörigen Feldtypen und
Aufzählungstypen.
S ≤ T impliziert M(S) ⊆ M(T )
Eine Klasse deklariert einen Typ und beschreibt Objekte diesen Typs,
d.h. u.a. deren öffentliche Schnittstelle und Implementierung.
• In Java wird die Subtyprelation im Wesentlichen zusammen mit
den Typdeklarationen definiert.
©Arnd Poetzsch-Heffter
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1171
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1172
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Schnittstellentypen in Java
Beispiel: (Schnittstellendeklaration)
Eine Schnittstellendeklaration deklariert einen Typ T und beschreibt
die öffentliche Schnittstelle, die alle Objekte von T haben.
interface Person {
String getName ();
int getGeburtsdatum ();
void drucken ();
boolean hat_geburtstag ( int datum );
}
Mögliche Implementierungen für Objekte von T liefern die echten
Subtypen von T .
Insbesondere lassen sich zu einem Schnittstellentyp T keine Objekte
erzeugen, die nur zu T gehören.
interface Druckbar {
void drucken ();
}
Syntax der Schnittstellendeklaration:
<Modifikatiorenlist > interface <Schnittstellenname >
[ extends <Liste von Schnittstellennamen > ]
{
<Liste von Konstantendekl . und Methodensignaturen >
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
interface Farbe {
byte gelb = 0;
byte gruen = 1;
byte blau = 2;
}
1173
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Subtypbildung in Java
1174
5.3 Subtypen und Vererbung
Beispiel: (Subtyprelation bei Schnittstellen)
1. Die Typen Person, Druckbar und Farbe haben nur Object als
Supertypen.
Die Deklaration eines Typs T legt fest, welche direkten Supertypen T
hat.
2. Der Typ Angestellte hat Person und Druckbar als direkte
Supertypen:
Bei einer Schnittstellendeklaration T gilt Folgendes:
interface Angestellte
extends Person , Druckbar {
String getName ();
int getGeburtsdatum ();
int getEinstellungsdatum ();
String getGehaltsklasse ();
void drucken ();
boolean hat_geburtstag ( int datum );
}
• Gibt es keine extends-Klausel, ist Object der einzige Supertyp.
• Andernfalls sind die in der extends-Klausel genannten
Schnittstellentypen die direkten Supertypen.
©Arnd Poetzsch-Heffter
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1175
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1176
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Subtypbildung in Java (2)
Subtypbildung in Java (3)
Eine Schnittstellendeklaration erweitert also die Schnittstelle eines
oder mehrerer anderer Typen.
Syntax der Klassendeklaration:
Methodensignaturen aus den Supertypen brauchen nicht nochmals
aufgeführt werden (Signaturvererbung):
<Modifikatiorenlist > class <Klassenname >
[ extends <Klassenname > ]
[ implements <Liste von Schnittstellennamen > ]
{
<Liste von Attribut -, Konstruktor -, Methodendekl .>
}
interface Angestellte
extends Person , Druckbar {
int getEinstellungsdatum ();
String getGehaltsklasse ();
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1177
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
1178
5.3 Subtypen und Vererbung
Beispiel: (Implementieren von Schnittstellen)
Eine Klassen erweitert eine direkte Superklasse (s. 5.3.3) und
implementiert ggf. mehrere Schnittstellentypen.
• Gibt es keine extends-Klausel, ist Object die direkte Superklasse.
Andernfalls ist die in der extends-Klausel genannte Klasse die
direkte Superklasse.
class Student implements Person , Druckbar {
private String name;
private int geburtsdatum ; // Form JJJJMMTT
private int matrikelnr ;
private int semester ;
public Student ( String n,int g,int m,int s){
name = n;
geburtsdatum = g;
matrikelnr = m;
semester = s;
}
public String getName () { return name; }
public int getGeburtsdatum () {
return geburtsdatum ;
}
• Die in der implements-Klausel genannten Schnittstellentypen
müssen implementiert werden.
Die Superklasse und alle implementierten Schnittstellentypen sind
Supertypen der deklarierten Klasse.
TU Kaiserslautern
TU Kaiserslautern
5. Objektorientiertes Programmieren
Subtypbildung in Java (4)
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
1179
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1180
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Beispiel: (Implementieren von Schnittstellen) (2)
}
Zusammenfassung: Typen & Subtyp-Ordnung:
public int getMatrikelnr () {
return matrikelnr ;
}
public int getSemester () { return semester ;}
public void drucken () {
System .out. println ("Name:"+ name);
System .out. println (" Gdatum :"+ geburtsdatum );
System .out. println (" Matnr :" + matrikelnr );
System .out. println (" Semzahl :"+ semester );
}
public boolean hat_geburtstag ( int datum ) {
return ( geburtsdatum %10000) ==(datum %10000) ;
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Typen:
- elementare Datentypen: int, char, byte, ....

- Schnittstellentypen 











- Klassentypen



Referenztypen





- Feldtypen









- Aufzählungstypen 
1181
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Zusammenfassung: Typen & Subtyp-Ordnung: (2)
1182
5.3 Subtypen und Vererbung
Realisierung von Klassifikationen:
Subtyp-Ordnung:
Deklaration:
impliziert
interface S extends T1 , T2 , ...
S <T1 ,
S <T2 , ...
Die Klassen bzw. Begriffe in einer Klassifikation können im Programm
durch Schnittstellen- oder Klassentypen realisiert werden.
Deklaration:
impliziert
class S extends T implements T1 , T2 , ...
S < T, S < T1 , S < T2 , ...
Wir betrachten die Klassifikation bestehend aus:
S < T impliziert:
Person, Druckbar, Student, Angestellte,
WissAngestellte und VerwAngestellte.
S[] < T[]
und davon die reflexive, transitive Hülle.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1183
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1184
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Realisierung von Klassifikationen: (2)
Realisierung von Klassifikationen: (3)
1. Variante:
Dazu die entsprechenden Typdeklarationen:
Nur die Blätter der Klassifikation (Student, WissAngestellte,
VerwAngestellte) werden durch Klassen realisert, alle anderen durch
Schnittstellen.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
interface Person { ... }
interface Druckbar { ... }
interface Angestellte
extends Person , Druckbar { ... }
class Student
implements Person , Druckbar {... }
class WissAngestellte
implements Angestellte { ... }
class VerwAngestellte
implements Angestellte { ... }
1185
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
1186
5.3 Subtypen und Vererbung
Realisierung von Klassifikationen: (4)
Realisierung von Klassifikationen: (5)
2. Variante:
Das Klassendiagramm zur 2. Variante:
Außer des Typs Druckbar realisieren wir alle Typen durch Klassen:
class Person { ... }
interface Druckbar { ... }
class Student extends Person
implements Druckbar
class Angestellte extends Person
implements Druckbar
class WissAngestellte
extends Angestellte
class VerwAngestellte
extends Angestellte
©Arnd Poetzsch-Heffter
TU Kaiserslautern
{ ... }
{ ... }
{ ... }
{ ... }
1187
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1188
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Diskussion:
5.3 Subtypen und Vererbung
Dynamische Methodenauswahl
Verwendung von Schnittstellen in Java:
• nur wenig über den Typ bekannt
Die Auswertung von Ausdrücken vom (statischen) Typ T kann
Ergebnisse haben, die von einem Subtyp sind.
• keine Festlegung von Implementierungsteilen
• als Supertyp von Klassen mit mehreren Supertypen
Damit stellt sich die Frage, wie Methodenaufrufe auszuwerten sind.
Hier sind die charakteristischen Beispiele:
Verwendung von Klassen in Java, wenn
• Objekte von dem Typ erzeugt werden sollen;
• Vererbung an Subtypen ermöglicht werden soll.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1189
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Beispiel: (Methodenaufruf)
Begriffsklärung: (dynamische Methodenauswahl)
Welche Methode soll ausgeführt werden:
Die auszuführende Methode zu einem Methodenaufruf:
<ZielAusdr >.< methodenName >( <AktParam1 >,...);
1. Auswahl zwischen Methode der Super- und Subklasse:
Frame f = new MemoFrame ();
...
f. setBackground ( Color .red );
wird wie folgt bestimmt:
1. Werte <ZielAusdr> aus; Ergebnis ist das Zielobjekt.
2. Auswahl zwischen Methode verschiedener Subklassen:
2. Werte die aktuellen Parameter <AktParam1>, ... aus.
static void alle_drucken ( Druckbar [] df) {
int i;
for( i =0; i<df. length ; i++) {
df[i]. drucken ();
}
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1190
3. Führe die Methode mit Namen <methodenName> des Zielobjekts
mit den aktuellen Parametern aus.
Dieses Verfahren nennt man dynamische Methodenauswahl oder
dynamisches Binden (engl. dynamic method binding).
1191
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1192
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Bemerkung:
5.3 Subtypen und Vererbung
Beispiel: (Erweiterbarkeit)
Wir gehen von einem Programm aus mit der Methode:
Die Unterstützung von Subtypen und dynamischer Methodenauswahl
ist entscheidend für die verbesserte Wiederverwendbarkeit und
Erweiterbarkeit, die durch Objektorientierung erreicht wird.
Zusätzlich werden diese Aspekte auch durch Vererbung unterstützt.
static void alle_drucken ( Druckbar [] df ) {
int i;
for( i =0; i<df. length ; i++) {
df[i]. drucken ();
}
}
Druckbar ist dabei Supertyp von Student, Angestellte, WissAngestellte
und VerwAngestellte.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1193
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Beispiel: (Erweiterbarkeit) (2)
Weitere Aspekte der Subtypbildung
Das Programm soll erweitert werden, um auch Professoren und
studentische Hilfskräfte behandeln zu können. Es reicht, zwei Klassen
hinzuzufügen:
Dieser Unterabschnitt behandelt detailliertere Aspekte zu
class Professor
implements Person , Druckbar
1194
• der Subtypordnung
{... }
• Typtest und Typkonvertierungen
class StudHilfskraft
extends Student { ... }
• Polymorphie
Eine Änderung des ursprünglichen Programms ist NICHT nötig!
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1195
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1196
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Aspekte der Subtypordnung
5.3 Subtypen und Vererbung
Aspekte der Subtypordnung (2)
Subtyprelation bei Feldern:
Zyklenfreiheit:
Jeder Feldtyp mit Komponenten vom Typ S ist ein Subtyp von Object:
Die Subtyprelation darf keine Zyklen enthalten (sonst wäre sie keine
Ordnung).
S[] ≤ Object
D.h. folgende Zuweisung ist zulässig:
Folgendes Fragment ist also in Java nicht zulässig:
Object ov = new String [3] ;
Ist S ≤ T , dann ist S[] ≤ T []. D.h. folgende Zuweisung ist zulässig:
interface C extends A { ... }
interface B extends C { ... }
interface A extends B { ... }
©Arnd Poetzsch-Heffter
Person [] pv = new Student [3] ;
Diese Festlegung der Subtypbeziehung zwischen Feldtypen ist in
vielen Fällen praktisch.
TU Kaiserslautern
5. Objektorientiertes Programmieren
1197
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Aspekte der Subtypordnung (3)
1198
5.3 Subtypen und Vererbung
Subtypen und elementare Datentypen:
Problem:
Statische Typsicherheit ist nicht mehr gegeben:
Zwischen den elementaren Datentypen und den Referenztypen gibt es
keine Subtypbeziehung:
String [] strfeld = new String [2];
Object [] objfeld = strfeld ;
objfeld [0] = new Object (); // Laufzeitfehler
// ArrayStoreException
int strl
= strfeld [0]. length ();
int Object , int boolean , double int
d.h. die folgenden Zuweisungen sind unzulässig:
boolean bv = 9;
int
iv = 3.4;
Speicherzustand nach der zweiten Zeile:
Wie in Haskell gibt es auch in Java die Möglichkeit, Werte eines
elementaren Datentyps in Werte eines anderen Datentyps zu
konvertieren (siehe unten).
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1199
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1200
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Subtypen und elementare Datentypen: (2)
5.3 Subtypen und Vererbung
Subtypen und elementare Datentypen: (3)
Javas Wrapper-Klassen sind im Paket java.lang definiert.
Der Zusammenhang zwischen elementaren Datentypen und
Referenztypen wird in Java über sogenannte Wrapper -Klassen erzielt.
Folgendes Diagramm zeigt die Subtypbeziehungen:
Ein Wrapper-Objekt für den elementaren Datentyp D besitzt ein
Attribut zur Speicherung von Werten des Typs D.
Anwendung von Wrapper-Klassen:
Integer ist die Wrapper-Klasse für den Typ int:
Integer iv = new Integer (7);
Object ov = iv;
int
n = iv. intValue () + 23 ;
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1201
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Boxing, Unboxing, Autoboxing
1202
5.3 Subtypen und Vererbung
Beispiel: (Autoboxing)
Das folgende Programmfragment mit Autoboxing
Die Umwandlung von Werten der elementaren Datentypen in Objekte
der Wrapper-Klassen nennt man Boxing, die umgekehrte
Umwandlung Unboxing.
List <Integer > ints = new ArrayList <Integer >();
ints.add (1);
int i = ints.get (0);
Wo nötig führt Java 6 Boxing und Unboxing automatisch durch
(Autoboxing).
ist eine Abkürzung von
©Arnd Poetzsch-Heffter
TU Kaiserslautern
List <Integer > ints = new ArrayList <Integer >();
ints.add(new Integer (1));
int i = ints.get (0). intValue ();
1203
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1204
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Bemerkungen:
5.3 Subtypen und Vererbung
Beispiel: (Comparable)
public interface Comparable {
public int compareTo ( Object o);
}
1. Autoboxing erlaubt es, Werte elementarer Datentypen einfacher
zusammen mit parameterischen Typen zu benutzen; kostet aber
Zeit und Speicher.
public class Main {
static boolean issorted ( Comparable [] cf ) {
int i;
if( cf.length <2 ) return true;
for( i=0; i<cf.length -1; i++) {
if( cf[i]. compareTo (cf[i+1]) > 0 ) {
return false;
}
}
return true;
}
2. Vorsicht: Objekte, die den gleichen Wert eingepackt haben,
müssen nicht gleich sein.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1205
5.3 Subtypen und Vererbung
TU Kaiserslautern
1206
5.3 Subtypen und Vererbung
Typkonvertierung von elementaren Typen:
Werte eines elementaren Datentyps lassen sich mittels sogenannter
Typkonvertierungen (engl. Cast) in Werte anderer Datentypen
konvertieren:
public static void main( String [] args ) {
boolean b;
Character [] cfv = new Character [4];
cfv [0] = new Character (’\’’);
cfv [1] = new Character (’Q’);
cfv [2] = new Character (’a’);
cfv [3] = new Character (’b’);
b = issorted (cfv);
System .out. println ("cfv sortiert : " + b );
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
Beispiel: (Comparable) (2)
}
©Arnd Poetzsch-Heffter
double
//
float
//
long
//
int
//
short
//
byte
//
1207
©Arnd Poetzsch-Heffter
dv
dv
fv
fv
lv
lv
iv
iv
sv
sv
bv
bv
= 3333533335.3333333;
== 3.3335333353333335 E9
= (float) dv;
== 3.33353344 E9
= (long) fv;
== 3333533440 L
= (int)
lv;
== -961433856
= (short) iv;
== -20736
= (byte) sv;
== 0
TU Kaiserslautern
1208
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Typkonvertierung von elementaren Typen: (2)
5.3 Subtypen und Vererbung
Typkonvertierung von Referenztypen:
Typkonvertierungen von Datentypen mit kleinerem Wertebereich in
solche mit größerem Wertebereich werden automatisch durchgeführt:
3.4 + 7
Bei Referenztypen prüft ein Cast, ob das geprüfte Objekt zu dem
entsprechenden Typ gehört:
• falls ja, wird die Ausführung fortgesetzt;
• falls nein, wird eine ClassCastException ausgelöst.
ist äquivalent zu:
3.4 + ( double ) 7
Bemerkung:
Casts auf Referenztypen sollten soweit möglich vermieden werden.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1209
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Beispiel: (Konvertieren von Referenztypen)
Typtest:
Number
nv
Object
ov
Number
nv1
Integer iwv
Integer iwv1
Float
fwv
Comparable c
String
sv
Java bietet außerdem den Operator instanceof zum Typtesten an:
©Arnd Poetzsch-Heffter
=
=
=
=
=
=
=
=
new Integer (7);
( Object ) nv; // upcast
( Object ) nv; //
nv;
//
( Integer ) nv; // downcast
(Float ) nv;
//
( Comparable ) nv; //
( String ) nv; //
TU Kaiserslautern
1210
Comparable c;
if( nv instanceof Comparable ) {
c = ( Comparable ) nv;
} else {
throw new ClassCastException ();
}
1211
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1212
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Polymorphie:
Beispiel: (Subtyp-Polymorphie)
In Kapitel 3 (Folie 418) hatten wir Polymorphie wie folgt erklärt:
Subtyp-Polymorphie erlaubt es insbesondere, inhomogene Listen zu
verwenden, d.h. Listen mit Element unterschiedlichen Typs:
Ein Typsystem heißt polymorph, wenn es Werte bzw. Objekte gibt,
die zu mehreren Typen gehören.
LinkedList ls = new LinkedList ();
ls. addLast (" letztes Element ");
(( String ) ls. getLast ()). indexOf ("Elem");
// liefert 8
ls. addLast ( new Float (3.3) );
// kein Uebersetzungsfehler
(( String ) ls. getLast ()). indexOf ("Elem");
// Laufzeitfehler
Begriffsklärung: (Subtyp-Polymorphie)
Die Form der Polymorphie in Typsystemen mit Subtypen heißt
Subtyp-Polymorphie.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1213
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Polymorphie im Vergleich:
1214
5.3 Subtypen und Vererbung
Beispiel: (Parametrische Listen)
Vergleich von Subtyp- und parametrischer Polymorphie:
• Subtyp-Polymorphie:
→ ermöglicht inhomogene Datenstrukturen;
→ benötigt keine Instanzierung von Typparametern;
→ ist sehr flexibel in Kombination mit dynamischer Methodenauswahl.
• parametrische Polymorphie:
LinkedList <String > ls =
new LinkedList <String >();
ls. addLast (" letztes Element ");
ls. getLast ()). indexOf ("Elem"); // liefert 8
ls. addLast ( new Float (3.3) );
// Uebersetzungsfehler !
ls. getLast (). indexOf ("Elem");
→ vermeidet Laufzeitprüfungen bei homogenen Datenstrukturen
(effizienter);
→ bietet mehr statische Prüfbarkeit (keine Ausnahmen zur Laufzeit).
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1215
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1216
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Programmieren mit Schnittstellentypen
5.3 Subtypen und Vererbung
Drei Implementierungen von Dictionary:
Wir demonstrieren die Anwendung von Schnittstellentypen an zwei
charakteristischen Beispielen:
In 3.2.2 wurden natürliche Suchbäume zur Realisierung der abstrakten
Datenstruktur DICTIONARY betrachtet.
1. Implementierungen einer abstrakten Datenstruktur mit
unterschiedlichen Laufzeit- und Speicherplatzeigenschaften:
Hier behandeln wir drei andere Suchverfahren:
Der Anwender der Datenstruktur wählt die Eigenschaften bei der
Erzeugung aus.
I Ansonsten benutzt die Anwendung nur die Methoden der
Schnittstelle.
→ Drei Implementierungen für Dictionary
I
• A. Binäre Suche in Feldern
• B. Balancierte Suchbäume
• C. Hashing/Streuspeicherung
2. Der Anwender eines Objekts kennt nur den Schnittstellentyp des
Objekts, aber nicht dessen Implementierung:
→ Beobachtermuster
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1217
5.3 Subtypen und Vererbung
1218
5.3 Subtypen und Vererbung
Drei Implementierungen von Dictionary: (3)
Dabei basiert die Verwaltung von Datensätzen auf drei
Grundoperationen:
Ziel ist es, Datenstrukturen zu finden, bei denen der Aufwand für obige
Operationen gering ist.
• Einfügen eines Datensatzes in eine Menge von Datensätzen;
Entsprechend der Signatur von put gehen wir im Folgenden davon
aus, dass ein Datensatz aus einem Schlüssel und einer Referenz vom
Typ Object besteht.
• Suchen eines Datensatzes mit Schlüssel k;
• Löschen eines Datensatzes mit Schlüssel k.
In vereinfachter Anlehnung an java.util.Dictionary legen wir folgende
Schnittstelle zugrunde:
class DataSet {
int key;
Object data;
DataSet (int k, Object d){ key=k; data=d; }
}
interface Dictionary {
Object get( int key );
void put( int key , Object value );
void remove ( int key );
}
TU Kaiserslautern
TU Kaiserslautern
5. Objektorientiertes Programmieren
Drei Implementierungen von Dictionary: (2)
©Arnd Poetzsch-Heffter
©Arnd Poetzsch-Heffter
1219
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1220
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Drei Implementierungen von Dictionary: (4)
A. Binäre Suche in Feldern
Wir betrachten drei Implementierungen des Schnittstellentyps
Dictionary und präsentieren jeweils
Lineare Datenstrukturen (Listen, Felder) mit einem Zugriff über den
Komponentenindex erlauben das Auffinden eines Datensatzes durch
binäre Suche.
• die Datenstruktur
(Hier betrachten wir eine Realisierung mit Feldern ähnlich wie in den
Übungen.)
• die drei grundlegenden Operationen
• eine einfache Komplexitätsabschätzung.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1221
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Datenstruktur:
1222
5.3 Subtypen und Vererbung
Datenstruktur: (2)
public class ArrayDictionary implements Dictionary
{
private DataSet [] elems;
private int
capacity ;
private int
size;
public ArrayDictionary () {
elems = new DataSet [8];
capacity
= 8;
size
= 0;
}
private int searchIndex ( int key ) { ... }
public Object get( int key ) { ... }
public void remove ( int key ) { ... }
public void put( int key , Object value ) {...}
}
Ein Dictionary wird repräsentiert durch ein Objekt mit:
• einer Referenz auf das Feld mit den Datensätzen
• der Größenangabe des Feldes (capacity)
• der Anzahl der gespeicherten Datensätze (size)
Die Operationen gewährleisten folgende Invariante:
• Die Datensätze sind aufsteigend sortiert.
• Die Schlüssel sind eindeutig.
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
1223
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1224
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Datenstruktur: (3)
Heraussuchen:
Zum Einfügen, Suchen und Löschen benötigt man den Index, an dem
die Operation ausgeführt werden soll:
private int searchIndex ( int key ) {
/* liefert Index ix von Datensatz mit
Schluessel k, wobei gilt:
- k == key , wenn so ein Eintrag vorhanden
- k ist naechst groessere Schluessel als key ,
zu dem Eintrag vorhanden
size , sonst
*/
...
}
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
1225
public Object get( int key ) {
int ix = searchIndex ( key );
if( ix == size || elems[ix]. key != key ){
return null;
} else {
return elems[ix ]. data;
}
}
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Löschen:
Einfügen:
public void remove ( int key ) {
int ix = searchIndex ( key );
if( ix!=size && elems [ix ]. key == key ){
/* Datensatz loeschen */
for( int i = ix +1; i<size; i++ ) {
elems [i -1] = elems [i];
}
size --;
}
}
public void put( int key , Object value ) {
int ix = searchIndex ( key );
if( ix == size || elems[ix]. key > key ) {
/* neuen Datensatz eintragen */
size ++;
if( size > capacity ) { // neues Feld anlegen
DataSet [] newElems = new DataSet [2* capacity ];
for( int i = 0; i<ix; i++ ) {
newElems [i] = elems[i];
}
for( int i = ix +1; i<size; i++ ) {
newElems [i] = elems[i -1];
}
elems = newElems ;
capacity = 2* capacity ;
Bemerkung:
Bei den Operationen ist eine schnelle Suche wichtig. Deshalb
konzentrieren sich die algorithmischen Untersuchungen auf diese
Operation.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1227
©Arnd Poetzsch-Heffter
1226
TU Kaiserslautern
1228
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Einfügen: (2)
5.3 Subtypen und Vererbung
Suchen
Das Arbeiten mit sortierten Feldern ermöglicht binäre Suche:
}
} else { // Elemente im Feld verschieben
for( int i = size -1; i<=ix +1; i-- ) {
elems [i] = elems[i -1];
}
}
elems [ix] = new DataSet ( key , value );
} else { // elems[ix ]. key == key
elems [ix ]. data = value ;
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
• Durch Vergleich mit Schlüssel des Datensatzes in der Feldmitte
kann bestimmt werden, ob der gesuchte Satz in der unteren oder
oberen Hälfte des Feldes liegt.
• Suche in der bestimmten Hälfte weiter.
private int searchIndex ( int key ) {
if( size==0 || elems[size -1]. key < key ){
return size;
} else {
int ug = 0;
int og = size -1;
/* key <= elems [og]. key */
1229
5.3 Subtypen und Vererbung
1230
5.3 Subtypen und Vererbung
Diskussion:
while ( ug <=og -2 ) {
int mid = ug + (og -ug)/2;
if( key < elems[mid ]. key ) {
og = mid;
} else {
ug = mid;
}
}
if( elems [ug]. key < key ) {
return og;
} else {
return ug;
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
Suchen (2)
} }
©Arnd Poetzsch-Heffter
TU Kaiserslautern
Binäres Suchen verursacht logarithmischen Aufwand: O(log N).
Ebenso das Herausholen eines Eintrags aus dem ArrayDictionary.
Einfügen und Löschen benötigen in der gezeigten Variante linearen
Aufwand: O(N).
Vorteile:
• einfach und speichersparend zu realisieren
• schnelles Heraussuchen von Einträgen
Nachteile:
• Einfügen und Löschen sind vergleichsweise langsam.
1231
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1232
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
B. Balancierte Suchbäume
Beispiel: (Strukturerhaltung)
In 3.2.2 haben wir natürliche binäre Suchbäume betrachtet. Sofern
binäre Suchbäume hinreichend gut ausgeglichen (balanciert) sind, ist
der Aufwand aller drei Grundoperationen logarithmisch.
Einfügen von 10 unter Erhaltung von Fast-Vollständigkeit
Ziel ist es, bei den modifizierenden Operationen den Baum wenn nötig
wieder auszubalancieren. (Wir betrachten hier nur das ausbalancieren
nach Einfüge-Operationen.)
Durch Anforderungen bzgl. einer Verteilung der Blätter und Höhen in
Unterbäumen kann man ein Degenerieren verhindern; Aspekte:
• Vorteil: geringer Aufwand für Grundoperationen kann zugesichert
werden.
• Nachteil: Strukturinvariante muss erhalten werden.
• Kosten der Strukturerhaltung?
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1233
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Beispiel: (Strukturerhaltung) (2)
1234
5.3 Subtypen und Vererbung
Begriffsklärung: (AVL-Baum)
Adelson-Velskij und Landis schlugen folgende
Balancierungseigenschaft vor:
Ein binärer Suchbaum heißt AVL-ausgeglichen, höhenbalanciert und
ein AVL-Baum, wenn für jeden Knoten K gilt:
Die Höhe des linken Unterbaums von K unterscheidet sich
von der Höhe des rechten Unterbaums höchstens um eins.
Wegen der Balancierungseigenschaft mussten alle Knoten vertauscht
werden.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1235
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1236
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Vorgehen zum Einsatz von AVL-Bäumen
Gestaltsanalyse:
Frage: Hat jeder AVL-Baum logarithmische Höhe?
(Dies ist die Voraussetzung, alle Grundoperationen mit
logarithmischen Aufwand realisieren zu können.)
• Gestaltsanalyse von AVL-Bäumen
• Rotationen auf Suchbäumen
Lemma:
• Datenstruktur für AVL-Bäume
Für die Höhe eines AVL-Baums mit N Knoten gilt:
• Heraussuchen
h ≤ 2 ∗ log(N + 1) + 1
• Balancieren nach Einfügen
Beweis:
siehe Vorlesung
• Diskussion
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
1237
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Rotationen auf Suchbäumen:
1238
5.3 Subtypen und Vererbung
Rotationen auf Suchbäumen: (2)
Eine Rotation ist ein lokale Reorganisation eines Suchbaums, bei der
die Suchbaumeigenschaft erhalten bleibt, die Höhen der Unterbäume
aber ggf. verändert werden.
Rotation nach rechts (nach links entsprechend):
Es gilt:
• alle Schlüssel aus A sind echt kleiner als X
• alle Schlüssel aus B sind echt größer als X und echt kleiner als Y
• alle Schlüssel aus C sind echt größer als Y
• X <Y
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1239
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1240
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Rotationen auf Suchbäumen: (3)
5.3 Subtypen und Vererbung
Datenstruktur für AVL-Bäume:
Doppelrotation links-rechts (rechts-links entsprechend):
Zur Realisierung von AVL-Bäumen gehen wir von der Implementierung
der natürlichen Suchbäume aus:
• Die Baumknoten bekommen ein zusätzliches Attribut bf (balance
factor), in dem die Höhendifferenz von linkem und rechtem
Unterbaum gespeichert wird.
• Die Operationen zum Einfügen und Löschen müssen angepasst
werden (ggf. wird dazu auch die Datenstruktur erweitert).
Auch bei der Doppelrotation bleibt die Suchbaumeigenschaft erhalten.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1241
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Datenstruktur für AVL-Bäume: (2)
1242
5.3 Subtypen und Vererbung
Datenstruktur für AVL-Bäume: (3)
Ein Dictionary wird repräsentiert durch ein Objekt, das eine Referenz
auf einen Binärbaum enthält:
• Die Baumknoten sind gekapselt und können von außen nur
• Der leere Binärbaum wird durch die null-Referenz repräsentiert
indirekt über die Grundoperationen manipuliert werden.
(leeres Dictionary).
• Jeder Knoten eines nichtleeren Binärbaums wird durch ein Objekt
vom Typ AVLNode repräsentiert mit Instanzvariablen für:
I
den Schlüssel
I
die Daten
I
die Referenz auf das linke Kind
I
die Referenz auf das rechte Kind
I
die Höhendifferenz bf
©Arnd Poetzsch-Heffter
Datenstruktur-Invarianten:
• Schlüssel kommen nicht doppelt vor.
• Die Binärbäume sind Suchbäume.
TU Kaiserslautern
• Die Höhendifferenz ist korrekt belegt.
1243
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1244
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Datenstruktur für AVL-Bäume: (4)
Datenstruktur für AVL-Bäume: (5)
class AVLTreeDictionary implements Dictionary
{
private AVLNode root;
private static class AVLNode {
private int key;
private Object data;
private AVLNode left , right ;
private int bf;
}
private AVLNode ( int k, Object d ) {
key = k;
data = d;
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
}
1245
public AVLTreeDictionary () {
root = null; // leeres Dictionary
}
public Object get( int key ) {.. .}
private AVLNode searchNode ( AVLNode current , int key)
{...}
public void put(int key , Object value) {...}
private AVLNode insertNode ( AVLNode curr , int key ,
Object v ) {...}
private AVLNode rotate ( AVLNode curr)
{...}
public void remove ( int key ) {
throw RuntimeException ("not available ");
}
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Heraussuchen:
1246
5.3 Subtypen und Vererbung
Heraussuchen: (2)
• Ist der Wurzelschlüssel gleich dem gesuchten Schlüssel,
terminiert das Verfahren.
• Ist der Wurzelschlüssel größer als der gesuchte Schlüssel, suche
im linken Unterbaum weiter.
• Ist der Wurzelschlüssel kleiner als der gesuchte Schlüssel, suche
im rechten Unterbaum weiter.
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
1247
public Object get( int key ) {
AVLNode tn = searchNode (root ,key);
if( tn == null ) {
return null;
} else {
return tn.data;
}
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1248
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Heraussuchen: (3)
Einfügen:
private AVLNode searchNode ( AVLNode current , int key)
{
if( current !=null && key != current .key ) {
if( current .key > key ) {
return searchNode ( current .left , key );
} else { // current .key < key
return searchNode ( current .right , key );
}
}
return current ;
}
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Entwicklung des Algorithmus in 4 Schritten:
1. Einfügen ohne Aktualisieren von bf und Rotation
2. Aktualisieren von bf, aber ohne Rotation
3. Aktualisieren von bf mit Aufruf der Rotation
4. Rotation mit Aktualisieren von bf an den rotierten Knoten
1249
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Einfügen: (2)
Beispiel:
1. Einfügen ohne Aktualisieren von bf und Rotation:
Einfügen von 33:
1250
5.3 Subtypen und Vererbung
• Neue Knoten werden immer als Blätter eingefügt.
• Die Position des Blattes wird durch den Schlüssel des neuen
Knotens festgelegt.
• Beim Aufbau eines Baumes ergibt der erste Knoten die Wurzel.
• Ein Knoten wird in den linken Unterbaum der Wurzel eingefügt,
wenn sein Schlüssel kleiner ist als der Schlüssel der Wurzel; in
den rechten, wenn er größer. Dieses Verfahren wird rekursiv
fortgesetzt, bis die Einfügeposition bestimmt ist.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1251
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1252
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
Beispiel: (2)
Rekursives Suchen der Einfügestelle und Einfügen:
class AVLTreeDictionary implements Dictionary
{
...
private AVLNode root;
...
public void put( int key , Object value ){
if( root == null ) {
root = new AVLNode (key , value);
} else {
AVLNode res = insertNode (root ,key , value);
if( res!=null ) root = res;
}
}
...
}
void insertNode ( AVLNode curr , int key , Object v ) {
// pre: curr != null
//
if( key < curr.key ) {
if ( curr.left == null ) {
curr.left = new AVLNode (key ,v);
} else {
insertNode ( curr.left , key , v);
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1253
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Rekursives Suchen der Einfügestelle und Einfügen:
(2)
}
©Arnd Poetzsch-Heffter
1254
5.3 Subtypen und Vererbung
2. Aktualisieren von bf, aber ohne Rotation
• Einfügen wie oben.
• Aktualisieren von bf soweit nötig:
Die Höhendifferenz bf kann sich nur bei Knoten ändern, die auf
} else if( key > curr.key ) {
if ( curr.right == null ) {
curr. right = new AVLNode (key ,v);
} else {
insertNode ( curr.right , key , v);
}
} else { // key == curr.key
curr.data = v;
}
dem Pfad von der Wurzel zum eingefügten Knoten liegen. Nur an
diesen Knoten kann die AVL-Eigenschaft verletzt werden.
• Bestimmen des kritischen Knotens KK; das ist der nächste
Elternknoten zum eingefügten Knoten mit |bf | = 2.
• Rotiere bei KK, Rotationstyp ergibt sich aus Pfad von eingefügtem
Knoten zu KK.
Wir werden zeigen, dass durch die Rotation der Unterbaum mit Wurzel
KK die gleiche Höhe erhält, die er vor dem Einfügen hatte.
Die Balancierungsfaktoren an Knoten oberhalb von KK brauchen also
nicht aktualisiert zu werden.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1255
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1256
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Einfügen mit Aktualisieren von bf:
Einfügen mit Aktualisieren von bf: (2)
private boolean insertNode ( AVLNode curr ,int key , Object v)
{ // pre: curr != null
// ens: result ==true , wenn h(curr) > old(h(curr))
//
result ==false , sonst
if( key < curr.key ) {
if( curr.left == null ) {
curr.left = new AVLNode (key ,v);
curr.bf ++; // |curr.bf| < 2
return (curr.bf >0);
} else {
if( insertNode (curr.left ,key ,v) ){
curr.bf ++;
return (curr.bf >0);
} else {
return false ;
} }
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1257
}
} else if( key > curr.key ) {
... // symmetrisch auf rechter Seite
} else { // key == curr.key
curr.data = v;
return false;
}
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
5. Objektorientiertes Programmieren
Bemerkung:
1258
5.3 Subtypen und Vererbung
3. Einfügen mit Aktualisieren von bf und Rotation:
• Die obige Fassung veranschaulicht die Vorgehensweise, auf dem
"Rückweg" von einem rekursiven Abstieg Operationen
auszuführen.
Problem: Die Rotation macht es nötig, den Elternknoten des
kritischen Knotens zu modifizieren.
Idee: Statt true/false liefert die Einfüge-Operation:
• Die obige Fassung wird so nicht benötigt, da bf nur bis zu
• null, wenn sich die Höhe geändert hat.
kritischen Knoten zu aktualisieren ist. Ist der kritische Knoten
gefunden, wird rotiert und damit die Aktualisierungen oberhalb
unnötig.
©Arnd Poetzsch-Heffter
5.3 Subtypen und Vererbung
TU Kaiserslautern
• Die Referenz auf den möglicherweise rotierten
Unterbaum, wenn sich die Höhe nicht geändert hat;
deshalb ist ggf. root zu modifizieren.
1259
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1260
Herunterladen