Algorithmen und Programmierung II
Übungsblatt 8 - Musterlösung
Aufgabe 1
a) - c)
class Buch {
String autor, titel;
int erscheinungsjahr;
Benutzer leser;
Buch naechstes;
Buch(String a, String t, int j) {
autor = a;
titel = t;
erscheinungsjahr = j;
}
void ausleihen(Benutzer b) throws Exception {
if (b == null) throw new Exception("kein Benutzer");
if (leser != null) throw new Exception("schon ausgeliehen");
leser = b;
naechstes = b.ausgeliehen;
b.ausgeliehen = this;
}
void zurueckgeben() throws Exception {
if (leser == null) throw new Exception("war gar nicht ausgeliehen");
Buch b = leser.ausgeliehen;
if (b == this)
leser.ausgeliehen = naechstes; else {
while (b.naechstes != this)
b = b.naechstes;
b.naechstes = naechstes;
}
leser = null;
naechstes = null;
}
public String toString() {
return "\t" + autor + ": " + titel + ". " + erscheinungsjahr +
(naechstes == null ? "": "\n" + naechstes);
}
}
class Benutzer {
int nummer;
String name, adresse;
Buch ausgeliehen;
Benutzer(int nu, String na, String a) {
nummer = nu;
name = na;
adresse = a;
}
public String toString() {
return "Name: " + name + "\nAdresse: " + adresse +
"\nMitgliedsnr: " + nummer + "\nausgeliehene Bücher:\n" +
(ausgeliehen == null ? "\t(keine)\n" : ausgeliehen + "\n");
}
}
d) Testmethode (Ausgabe)
public static void main(String[] args) {
Buch b1 = new Buch("H. Mössenböck", "Sprechen Sie Java?", 2001);
Buch b2 = new Buch("James Gosling et al",
"The Java Language Specification", 2000);
Buch b3 = new Buch("David Flanagan", "Java in a Nutshell", 2002);
Benutzer n1 = new Benutzer(2309, "Max Mustermann", "Takustr. 9");
Benutzer n2 = new Benutzer(2310, "Torsten Test", "Arnimallee 2-6");
System.out.println("Benutzer ohne Bücher: \n\n" + n1);
try {
b1.ausleihen(n1);
b2.ausleihen(n1);
b3.ausleihen(n1);
System.out.println("Benutzer mit Büchern:\n\n" + n1);
b1.ausleihen(n2);
} catch (Exception e) {
System.out.println("doppeltes Ausleihen: " + e + "\n");
}
try {
b3.zurueckgeben();
System.out.println("vorderstes Buch zurückgegeben:\n\n" + n1);
b1.zurueckgeben();
System.out.println("hinterstes Buch zurückgegeben:\n\n" + n1);
b3.ausleihen(n2);
System.out.println("Buch wieder verleihen:\n\n" + n2);
b1.zurueckgeben();
} catch (Exception e) {
System.out.println("doppeltes Zurückgeben: " + e);
}
}
Aufgabe 2
a) "herkömmlich"
static int zeroLineA(float[][] a) throws Exception {
int k;
outer: for (int i = 1; i < a.length; i++) {
for (k = 1; k < a[i].length; k++)
if (a[i][k] != 0) continue outer;
return i;
}
throw new Exception("keine Zeile gefunden");
}
b) Sentinel-Technik
static int zeroLineB(float[][] a) throws Exception {
int i, k;
a[0] = new float[1];
for (i = a.length-1; ; i--) {
a[i][0] = 1;
for (k = a[i].length-1; a[i][k] == 0; k--) ;
if (k == 0) break;
}
if (i > 0) return i;
throw new Exception("keine Zeile gefunden");
}
c) mit Exceptions
static int zeroLineC(float[][] a) throws Exception {
int i, k;
for (i = 1; ; i++) {
k = 1;
try {
while (a[i][k++] == 0) ;
} catch (IndexOutOfBoundsException e) {
if (i == a.length)
throw new Exception("keine Zeile gefunden");
else return i;
}
}
}
d) Einfachheit und gute Verständlichkeit sprechen
für Variante a). Hier wird am schnellsten ersichtlich, wie die
Methode funktioniert, was bei späterem Lesen und Verifizieren des
Codes vorteilhaft ist.
Die Verwendung der Sentinel-Technik kann hier als Optimierung
betrachtet werden. Man spart pro Schleifendurchgang den Test, ob sich
der Index noch innerhalb der Feldgrenzen befinden. Dies wird sich
jedoch erst bei sehr großen Matrizen oder sehr vielen Aufrufen
der Methode bemerkbar machen. Optimierungen sollten normalerweise erst
dann durchgeführt werden, wenn tatsächlich begründet
werden kann, dass eine Optimierung an dieser Stelle einen hinreichend
großen Effekt auf die Performanz der gesamten Anwendung hat.
Andernfalls ist besser lesbarer Code vorzuziehen.
Das Erkennen von Feldgrenzenüberschreitungen anhand von Ausnahmen
ist normalerweise nicht zu empfehlen. Ausnahmen sind nicht dazu
gedacht, den Kontrollfluss auf diese Weise zu steuern. Der Code ist
recht schlecht lesbar. Die Effizienz ist stark von der Größe
der Matrix und der Aufrufhäufigkeit abhängig. Bei einer sehr
großen Matrix ist die Variante c) schneller als die beiden
anderen Varianten: Das Durchsuchen der Matrix ist sehr effizient, erst
am Ende wird das Auftreten einer Ausnahme in Kauf genommen. Das
Auftreten und Behandeln einer Ausnahme ist allerdings recht teuer.
Werden nur kleine Matrizen verarbeitet und wird die Methode sehr
häufig aufgerufen, so überwiegen die Kosten für die
Ausnahmebehandlung, und Variante c) ist wesentlich schlechter als die
ersten beiden.