Einführung in die Informatik I Kapitel 6: Reihungen, Sortieren und ...
Einführung in die Informatik I Kapitel 6: Reihungen, Sortieren und ...
Einführung in die Informatik I Kapitel 6: Reihungen, Sortieren und ...
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I<br />
Prof. Bernd Brügge, Ph.D.<br />
Technis/che Universität München<br />
W<strong>in</strong>tersemester 2003/2004<br />
<strong>Kapitel</strong> 6:<br />
<strong>Reihungen</strong>, <strong>Sortieren</strong> <strong>und</strong> Suchen<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 1<br />
2
Überblick über <strong>die</strong>sen Vorlesungsblock<br />
v Themen:<br />
– <strong>Reihungen</strong> (arrays): e<strong>in</strong>- <strong>und</strong> mehrdimensionale <strong>Reihungen</strong><br />
– Werte <strong>und</strong> Referenzsemantik<br />
– Parameterübergaben (Wert <strong>und</strong> Referenzübergaben)<br />
– <strong>Sortieren</strong> von <strong>Reihungen</strong><br />
– Suchen <strong>in</strong> <strong>Reihungen</strong><br />
v Ziele:<br />
– Sie s<strong>in</strong>d <strong>in</strong> der Lage, Probleme zu lösen, <strong>die</strong> e<strong>in</strong>e Menge von Daten<br />
erfordern.<br />
– Sie verstehen den Unterschied zwischen e<strong>in</strong>fachen Variablen <strong>und</strong><br />
Referenzvariablen.<br />
– Sie können aktiv mit <strong>Reihungen</strong> umgehen, <strong>in</strong>sbesondere <strong>in</strong> der<br />
Implementation von Algorithmen.<br />
– Sie s<strong>in</strong>d <strong>in</strong> der Lage, Probleme zu lösen, <strong>die</strong> Daten mit mehreren<br />
Dimensionen erfordern.<br />
– Sie beherrschen erste Sortierverfahren: bubble sort, selection sort,<br />
<strong>in</strong>sertion sort<br />
– Sie können <strong>in</strong> <strong>Reihungen</strong> effizient suchen.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 2
<strong>Reihungen</strong><br />
v E<strong>in</strong>e Reihung (array) ist e<strong>in</strong>e Menge von Variablen, <strong>die</strong> Werte<br />
desselben Typs speichern.<br />
v E<strong>in</strong>e e<strong>in</strong>zelne Variable wird nicht durch ihren Namen benannt,<br />
sondern durch ihre Position <strong>in</strong>nerhalb der Reihung.<br />
v Beispiel: Ausgabe der Studentennamen, <strong>die</strong> <strong>in</strong> e<strong>in</strong>em Verzeichnis<br />
gespeichert s<strong>in</strong>d:<br />
Ohne Reihung<br />
System.out.pr<strong>in</strong>tln(student1);<br />
System.out.pr<strong>in</strong>tln(student2);<br />
System.out.pr<strong>in</strong>tln(student3);<br />
System.out.pr<strong>in</strong>tln(student4);<br />
System.out.pr<strong>in</strong>tln(student5);<br />
System.out.pr<strong>in</strong>tln(student6);<br />
System.out.pr<strong>in</strong>tln(student7);<br />
Mit Reihung<br />
for (<strong>in</strong>t k = 1; k
1-dimensionale <strong>Reihungen</strong><br />
v E<strong>in</strong>e Variable <strong>in</strong> e<strong>in</strong>er Reihung wird durch ihre Position <strong>in</strong>nerhalb der<br />
Reihung bezeichnet, nicht durch e<strong>in</strong>en eigenen Bezeichner.<br />
– In e<strong>in</strong>er Reihung von n Variablen mit dem Bezeichner arr werden <strong>die</strong><br />
Variablen so benannt: arr[0],arr[1],arr[2],…,arr[n-1].<br />
v Die folgende Reihung umfasst 8 Variablen vom Typ <strong>in</strong>t.<br />
Die Indizierung<br />
von <strong>Reihungen</strong><br />
beg<strong>in</strong>nt <strong>in</strong> Java<br />
immer bei 0<br />
arr:<br />
Index<br />
0 1 2 3 4 5 6 7<br />
-2 8 -1 16 16 45 21 -3<br />
Reihungsname<br />
Syntax e<strong>in</strong>er Reihungsdeklaration:<br />
typbezeichner[] arrayname;<br />
wobei<br />
- arrayname der Name der Reihung ist, <strong>und</strong><br />
- typbezeichner der Typ der Reihungsvariablen.<br />
Elementwert<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 4
Term<strong>in</strong>ologie<br />
v E<strong>in</strong>e leere Reihung enthält ke<strong>in</strong>e Variablen.<br />
v Die Variablen <strong>in</strong> e<strong>in</strong>er Reihung heißen auch Reihungselemente oder<br />
kurz Elemente.<br />
v Jedes Element <strong>in</strong> e<strong>in</strong>er Reihung hat denselben Typ, auch Elementtyp<br />
genannt.<br />
v Die Länge e<strong>in</strong>er Reihung ist <strong>die</strong> Anzahl ihrer Elemente.<br />
v Jedes Reihungsobjekt hat e<strong>in</strong> Attribut length, das <strong>die</strong> Länge der<br />
Reihung angibt.<br />
– arr.length ist im Beispiel der vorigen Folie gleich 8.<br />
v Reihungselemente können beliebige Typen se<strong>in</strong>, e<strong>in</strong>schließlich<br />
<strong>Reihungen</strong> <strong>und</strong> Klassen.<br />
– In Java: E<strong>in</strong>e 2-dimensionale Reihung ist e<strong>in</strong>e Reihung von<br />
<strong>Reihungen</strong> von Elementen e<strong>in</strong>es Typs<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 5
Zugriff auf Elemente <strong>in</strong> e<strong>in</strong>er Reihung<br />
arr:<br />
Gegeben seien <strong>die</strong> Deklarationen: <strong>in</strong>t j = 5, k = 2;<br />
Gültige Elementzugriffe s<strong>in</strong>d:<br />
arr[1] // Bezeichnet den Wert 8<br />
arr[0] // Bezeichnet den Wert -2<br />
arr[j + k] // Ergibt arr[5+2], d.h. arr[7], also -3<br />
arr[j % k] // Ergibt arr[5%2], d.h. arr[1], also 8<br />
Ungültige Elementzugriffe:<br />
-2 8 -1 16 16 45 21 -3<br />
arr[5.0] // 5.0 ist e<strong>in</strong>e Gleitkommazahl (double),<br />
// kann also nicht Index se<strong>in</strong>.<br />
arr['5'] // '5' ist vom Typ char, nicht von Typ <strong>in</strong>t<br />
arr[-1] // Negative Indizes s<strong>in</strong>d nicht möglich.<br />
arr[8] // Das letzte Element von arr hat Index 7<br />
arr[j*k] // j*k ist gleich 10, als außerhalb des<br />
// Indexbereiches<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 6
Deklaration <strong>und</strong> Instantiierung e<strong>in</strong>er Reihung<br />
v Um e<strong>in</strong>e 1-dimensionale Reihung zu deklarieren, müssen wir den<br />
Namen der Reihung <strong>und</strong> auch den Typ der Elemente angeben.<br />
v Um e<strong>in</strong>e Reihung zu <strong>in</strong>stantiieren, müssen wir den new-Operator<br />
benutzen, der den Elementtyp <strong>und</strong> <strong>die</strong> Länge der Reihung benötigt.<br />
<strong>in</strong>t[] arr;<br />
// Deklaration e<strong>in</strong>er Reihung<br />
arr = new <strong>in</strong>t[15]; // Instantiierung e<strong>in</strong>er Reihung von 15<br />
// Elementen<br />
Wir können beide Aktivitäten <strong>in</strong> e<strong>in</strong>em Schritt vere<strong>in</strong>en:<br />
<strong>in</strong>t[] arr = new <strong>in</strong>t[15];<br />
Der Name der<br />
Reihung ist arr.<br />
Die Reihung enthält 15<br />
Variablen vom Typ <strong>in</strong>t.<br />
Die 15 Variablen: arr[0], arr[1], .., arr[14]<br />
Indexwerte von 0 bis arr.length-1 zulässig.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 7
Was genau passiert bei Deklaration <strong>und</strong><br />
Instantiierung e<strong>in</strong>er Reihung?<br />
Deklaration e<strong>in</strong>er Reihungsvariable:<br />
<strong>in</strong>t[] arr;<br />
Nach der Deklaration ist der Wert<br />
der Reihungsvariable null.<br />
arr: null<br />
Die new-Operation <strong>in</strong>stantiiert e<strong>in</strong>e<br />
Reihung, deren Inhalte mit dem<br />
Default-Wert 0 vorbesetzt s<strong>in</strong>d.<br />
new <strong>in</strong>t[8]<br />
0 0 0 0 0 0 0 0<br />
Die Zuweisung ersetzt den null-Wert durch e<strong>in</strong>en Verweis auf das<br />
Reihungsobjekt.<br />
arr = new <strong>in</strong>t[8];<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 8
Initialisierung von <strong>Reihungen</strong><br />
v Bei der Deklaration werden <strong>Reihungen</strong> <strong>und</strong> Reihungselemente <strong>in</strong><br />
Java mit Vore<strong>in</strong>stellungswerten (default values) <strong>in</strong>itialisiert:<br />
– Reihungsvariablen werden auf den Wert null <strong>in</strong>itialisiert.<br />
– Reihungselemente mit Typen <strong>in</strong>t, boolean, … werden auf 0,<br />
false, ... <strong>in</strong>itialisiert.<br />
v Reihungselemente kann man bereits bei der Deklaration der<br />
Reihung mit <strong>in</strong>itialen Werten versehen:<br />
<strong>in</strong>t[] arr = {-2,8,-1,-3,16,20,25,16,16,8,18,19,45,21,-2};<br />
Regel: Wenn e<strong>in</strong>e Reihung bereits bei der Deklaration <strong>in</strong>itialisiert wird,<br />
dann brauchen wir den new-Operator nicht mehr, um <strong>die</strong> Reihung zu<br />
kreieren (<strong>die</strong> Instantiierung der Reihung hat bereits bei der Deklaration<br />
stattgef<strong>und</strong>en!).<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 9
Zuweisung <strong>und</strong> Benutzung von Reihungswerten<br />
Indizierte Reihungsariablen benutzen wir genauso wie andere<br />
Variablen:<br />
arr[0] = 5;<br />
arr[5] = 10;<br />
arr[2] = 3;<br />
E<strong>in</strong> Programmstück, das <strong>die</strong> ersten 15 Quadratzahlen (1, 4, 9, 16, …)<br />
der Reihung arr zuweist:<br />
<strong>in</strong>t[] array = new <strong>in</strong>t[15];<br />
for (<strong>in</strong>t k = 0; k < arr.length; k++)<br />
arr[k] = (k+1) * (k+1);<br />
E<strong>in</strong>e Schleife zum Drucken der Werte von arr:<br />
for (<strong>in</strong>t k = 0; k < arr.length; k++)<br />
System.out.pr<strong>in</strong>tln(arr[k]);<br />
Wichtig: length<br />
ist e<strong>in</strong> Attribut von<br />
arr, ke<strong>in</strong>e Methode.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 10
Beispiel: Ausdruck von Werten<br />
Drucke e<strong>in</strong>e Reihung für Elemente vom Typ <strong>in</strong>t <strong>und</strong> e<strong>in</strong>e Reihung<br />
für Elemente vom Typ double:<br />
public class Pr<strong>in</strong>tArrays {<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) {<br />
<strong>in</strong>t <strong>in</strong>tArr[] = new <strong>in</strong>t[10]; // Kreiere <strong>die</strong> Reihung <strong>in</strong>tArr<br />
double realArr[] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8,<br />
9.9, 10.10 }; // <strong>und</strong> e<strong>in</strong>e vor<strong>in</strong>itialisierte<br />
// Reihung von Gleitkommawerten<br />
System.out.pr<strong>in</strong>tln("Int \t Double");<br />
Int Double<br />
for (<strong>in</strong>t k = 0; k < <strong>in</strong>tArr.length; k++)<br />
0 1.1<br />
System.out.pr<strong>in</strong>tln( <strong>in</strong>tArr[k] + " \t " + realArr[k]);<br />
0 2.2<br />
0 3.3<br />
0 4.4<br />
0 5.5<br />
0 6.6<br />
0 7.7<br />
0 8.8<br />
0 9.9<br />
0 10.1<br />
} // ma<strong>in</strong>()<br />
} // Pr<strong>in</strong>tArrays<br />
Die Reihung <strong>in</strong>tArr ist nicht <strong>in</strong>itialisiert,<br />
alle Elemente haben also<br />
Vore<strong>in</strong>stellungswerte 0.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 11
Beispiel: Speichere <strong>und</strong> drucke 100 Quadratzahlen<br />
public class Squares {<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g args[]) {<br />
f<strong>in</strong>al <strong>in</strong>t ARRSIZE = 100;<br />
// Größe der Reihung ist e<strong>in</strong>e Konstante<br />
<strong>in</strong>t <strong>in</strong>tArr[] = new <strong>in</strong>t[ARRSIZE]; // Deklariere <strong>und</strong> kreiiere <strong>die</strong><br />
// Reihung<br />
for (<strong>in</strong>t k = 0; k < <strong>in</strong>tArr.length; k++) // Initialisierung der Reihung<br />
<strong>in</strong>tArr[k] = (k+1) * (k+1);<br />
System.out.pr<strong>in</strong>t("Die ersten 100 Quadratzahlen:"); // Kopf der Tabelle<br />
for (<strong>in</strong>t k = 0; k < <strong>in</strong>tArr.length; k++) {<br />
// Drucke <strong>die</strong> Reihung<br />
if (k % 10 == 0)<br />
// 10 Elemente pro Reihe<br />
System.out.pr<strong>in</strong>tln(" ");<br />
System.out.pr<strong>in</strong>t( <strong>in</strong>tArr[k] + " ");<br />
} // for<br />
} // ma<strong>in</strong>()<br />
} // Squares<br />
Die ersten 100 Quadratzahlen:<br />
1 4 9 16 25 36 49 64 81 100<br />
121 144 169 196 225 256 289 324 361 400<br />
441 484 529 576 625 676 729 784 841 900<br />
961 1024 1089 1156 1225 1296 1369 1444 1521 1600<br />
1681 1764 1849 1936 2025 2116 2209 2304 2401 2500<br />
2601 2704 2809 2916 3025 3136 3249 3364 3481 3600<br />
3721 3844 3969 4096 4225 4356 4489 4624 4761 4900<br />
5041 5184 5329 5476 5625 5776 5929 6084 6241 6400<br />
6561 6724 6889 7056 7225 7396 7569 7744 7921 8100<br />
8281 8464 8649 8836 9025 9216 9409 9604 9801 10000<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 12
Zuweisung von <strong>Reihungen</strong><br />
Wir kennen schon <strong>die</strong> Situation nach folgender Deklaration <strong>und</strong><br />
Instantiierung: <strong>in</strong>t[] a = new <strong>in</strong>t[8];<br />
a:<br />
0 0 0 0 0 0 0 0<br />
Was passiert nun, wenn wir e<strong>in</strong>e zweite Reihungsvariable<br />
deklarieren <strong>und</strong> ihr den Wert von a zuweisen? <strong>in</strong>t[] b = a;<br />
Das Reihungsobjekt wird <strong>in</strong> Java nicht etwa kopiert,<br />
a:<br />
b:<br />
0 0 0 0 0 0 0 0<br />
0 0 0 0 0 0 0 0<br />
sondern es entsteht e<strong>in</strong> zweiter Verweis auf dasselbe Objekt!<br />
a:<br />
0 0 0 0 0 0 0 0<br />
b: Änderungen an b wirken sich ab sofort auch auf a aus!<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 13
<strong>Reihungen</strong> s<strong>in</strong>d Objekte<br />
v In Java werden <strong>Reihungen</strong> (arrays) wie Objekte behandelt:<br />
– Sie werden mit dem new Operator <strong>in</strong>stantiiert.<br />
– Sie haben Attribute (<strong>in</strong>stance variables), z.B. length.<br />
– Allerd<strong>in</strong>gs: Es gibt ke<strong>in</strong>e "Klasse" Array <strong>in</strong> Java.<br />
v In Java gibt es 2 Arten von Variablen:<br />
– E<strong>in</strong>fache Variable:<br />
u Variable vom Typ <strong>in</strong>t, float, double, boolean<br />
– Referenzvariable:<br />
u Variable vom Typ array oder e<strong>in</strong>er benutzerdef<strong>in</strong>ierten Klasse<br />
(z.B. Student) oder e<strong>in</strong>er vordef<strong>in</strong>ierten Klasse (z.B. Str<strong>in</strong>g).<br />
v Die Semantik bei Zuweisungen an <strong>die</strong>se Variablen ist verschieden:<br />
– Wertesemantik für e<strong>in</strong>fache Variable<br />
– Referenzsemantik für Referenzvariablen<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 14
Wertesemantik von Variablen<br />
v E<strong>in</strong>e Variable ist def<strong>in</strong>iert als e<strong>in</strong> Tupel (Name, Wert).<br />
– Der Name ist genauer gesagt e<strong>in</strong>e Zugriffsfunktion,<br />
mit der wir den "Platz" der Variablen berechnen, <strong>und</strong><br />
dann den Wert lesen oder ihn schreiben.<br />
Name<br />
a :<br />
Wert<br />
5<br />
<strong>in</strong>t a, b; a = 5; b = 8;<br />
Zugriffsfunktion<br />
v Wir nennen <strong>die</strong>se Auffassung <strong>die</strong> Wertsemantik von<br />
Variablen:<br />
– Wir bezeichnen Variablen mit Wertsemantik auch als<br />
Wertobjekte <strong>und</strong> ihre Typen als Werttypen.<br />
– Beispiele von Wertobjekten: Variable vom Typ boolean, <strong>in</strong>t,<br />
char, float, double.<br />
v Bei Wertobjekten kann man direkt auf <strong>die</strong> Werte über den<br />
Namen zugreifen.<br />
b :<br />
8<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 15
Referenzsemantik von Variablen<br />
Verweisvariable<br />
v E<strong>in</strong>e Variable mit Referenzsemantik ist immer noch e<strong>in</strong><br />
Tupel (Name, Wert). Allerd<strong>in</strong>gs<br />
– Der Wert ist jetzt e<strong>in</strong>e Referenz (Verweis,<br />
"Addresse", "Po<strong>in</strong>ter") auf e<strong>in</strong>e Variable <strong>die</strong><br />
als Wert e<strong>in</strong> Objekt hat (z.B. <strong>die</strong> Instanz<br />
e<strong>in</strong>er Klasse oder e<strong>in</strong>e Reihung).<br />
u Diese Variable wird auch Verweisvariable<br />
genannt.<br />
Name<br />
stud1<br />
:<br />
Student<br />
x45454423<br />
Student stud1, stud2;<br />
stud1 = new Student()<br />
Zugriffsfunktionen<br />
stu<strong>die</strong>rt<br />
denkt<br />
schlaeft<br />
stu<strong>die</strong>re()<br />
denke()<br />
schlafe()<br />
true<br />
false<br />
false<br />
stud2<br />
:<br />
null<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 16
Variable mit Referenzsemantik:<br />
Das Ganze noch e<strong>in</strong>mal<br />
Verweisvariable<br />
Name<br />
student stud1, stud2;<br />
stud1 = new Student();<br />
Zugriffsfunktionen<br />
stud1<br />
:<br />
x45454423 null<br />
Der Wert der Verweisvariablen<br />
ist e<strong>in</strong>e Referenz<br />
auf e<strong>in</strong> Objekt vom Typ<br />
Student<br />
Student<br />
stu<strong>die</strong>rt<br />
denkt<br />
schlaeft<br />
true<br />
false<br />
false<br />
Verweisvariable<br />
stu<strong>die</strong>re()<br />
denke()<br />
schlafe()<br />
Name<br />
stud2<br />
:<br />
null<br />
Die Verweisvariable<br />
hat noch den Wert null<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 17
Folie 43 aus <strong>Kapitel</strong> 5:<br />
Zuweisung von Referenzen auf Objekte<br />
v E<strong>in</strong>e Variable kann nicht nur Werte wie false oder 100 speichern,<br />
sondern auch e<strong>in</strong>en Verweis (“Referenz”, “Addresse”) auf e<strong>in</strong> Objekt.<br />
Student stud1, stud2; // Deklaration von 2 Variablen<br />
stud1 = new Student(); // Erzeugt Objekt vom Typ Student<br />
Nach der Instantiierung<br />
verweist stud1 auf e<strong>in</strong><br />
Objekt vom Typ Student.<br />
stud1<br />
Die andere Variable stud2 kann irgendwann<br />
mal auf e<strong>in</strong> Student-Objekt verweisen, aber<br />
ihre Referenz ist zur Zeit nicht def<strong>in</strong>iert (null).<br />
stud2<br />
Student<br />
stu<strong>die</strong>rt<br />
denkt<br />
schlaeft<br />
stu<strong>die</strong>re()<br />
denke()<br />
schlafe()<br />
true<br />
false<br />
false<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 18
Referenzsemantik <strong>in</strong> Java<br />
v Für Reihungsvariable <strong>und</strong> für alle Objekte von<br />
benutzerdef<strong>in</strong>ierten Klassen gilt <strong>die</strong> Referenzsemantik.<br />
v Bei der Parameterübergabe von Referenzvariablen wird <strong>die</strong><br />
Referenz zur Reihung oder zum Objekt übergeben (call by<br />
reference), nicht e<strong>in</strong>e Kopie (call by value) der ganzen Elemente.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 19
Parameterübergabe bei Methodenaufrufen:<br />
Wertesemantik<br />
Call by Value: Beim Methodenaufruf übergeben wir der Wert des<br />
aktuellen Parameters (z.B. e<strong>in</strong>er Variablen) aus dem aufrufenden<br />
Programm an den formalen Parameter der Methode: Hierbei wird der<br />
Parameter durch e<strong>in</strong>e Kopie des Variablenwertes ersetzt. Zuweisungen an<br />
<strong>die</strong> Kopie haben ke<strong>in</strong>en Effekt auf <strong>die</strong> Variable:<br />
n bekommt den<br />
Wert von Num<br />
public void add1(<strong>in</strong>t n) {<br />
System.out.pr<strong>in</strong>tln("n = " + n);<br />
n = n + 1;<br />
System.out.pr<strong>in</strong>tln("n = " + n);<br />
}<br />
Alle Zuweisungen an den Parameter n <strong>in</strong>nerhalb der Methode add1() s<strong>in</strong>d<br />
lokal, <strong>und</strong> existieren nicht ausserhalb des Methodenaufrufes.<br />
<strong>in</strong>t Num = 5;<br />
System.out.pr<strong>in</strong>tln("Num = " + Num);<br />
add1(Num);<br />
System.out.pr<strong>in</strong>tln("Num = " + Num);<br />
ergibt<br />
Num = 5<br />
n = 5<br />
n = 6<br />
Num = 5<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 20
Parameterübergabe bei Methodenaufrufen: (18.11.2003)<br />
Referenzsemantik<br />
Call by Reference: In <strong>die</strong>sem Fall wird nicht der Wert, sondern <strong>die</strong><br />
Referenz ("Addresse") des aktuellen Parameters (z.B. e<strong>in</strong>er Objektes<br />
oder e<strong>in</strong>er Reihung) e<strong>in</strong>er Methode übergeben. Zuweisungen an das<br />
Objekt existieren auch ausserhalb des Methodenaufrufs.<br />
<strong>in</strong>t[] <strong>in</strong>tArr = { 21, 20, 27, 24, 19 }; // Initialisierung<br />
Sort sorter = new Sort();<br />
sorter.pr<strong>in</strong>t(<strong>in</strong>tArr);<br />
// Drucke<br />
sorter.bubbleSort(<strong>in</strong>tArr);<br />
// Sortiere<br />
sorter.pr<strong>in</strong>t(<strong>in</strong>tArr);<br />
// Drucke noch mal<br />
ergibt<br />
21 20 27 24 19<br />
19 20 21 24 27<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 21
Zusammenfassung: Referenzvariablen <strong>in</strong> Java<br />
v In Java s<strong>in</strong>d Variablen <strong>in</strong> der Regel Referenzvariablen!<br />
– Ausnahme: Variablen e<strong>in</strong>facher Typen wie <strong>in</strong>t, double,<br />
boolean<br />
v Bei der Zuweisung werden nicht <strong>die</strong> referenzierten Objekte kopiert<br />
sondern lediglich <strong>die</strong> Verweise auf <strong>die</strong>se Objekte.<br />
– Es entstehen mehrfache Verweise auf dasselbe Objekt.<br />
– Änderungen über den e<strong>in</strong>en Verweis (über <strong>die</strong> e<strong>in</strong>e Variable)<br />
bee<strong>in</strong>flussen also Objekte, <strong>die</strong> auch über den anderen Verweis (über<br />
<strong>die</strong> andere Variable) erreicht werden.<br />
– Es entsteht also das sogenannnte Aliasnamen-Problem.<br />
v Auch bei der Parameterübergabe (call by value) werden nur Verweise<br />
kopiert, nicht jedoch <strong>die</strong> referenzierten Objekte.<br />
v In Programmiersprachen wie Pascal dagegen werden bei der Zuweisung<br />
von Reihungsvariablen auch <strong>die</strong> Inhalte kopiert.<br />
– Das Referenzkonzept muss dort explizit angefordert werden.<br />
– Z.B. bei der Parameterübergabe <strong>in</strong> Pascal mittels var.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 22
Mehrdimensionale <strong>Reihungen</strong><br />
v Mehrdimensionale <strong>Reihungen</strong> s<strong>in</strong>d <strong>in</strong> Java <strong>Reihungen</strong>, deren Elemente<br />
<strong>Reihungen</strong> s<strong>in</strong>d, deren Elemente wiederum <strong>Reihungen</strong> s<strong>in</strong>d, usw.<br />
v Beispiel: 2-dimensionale<br />
Matrix aus 3 Zeilen <strong>und</strong><br />
4 Spalten ganzer Zahlen:<br />
1 2 3 4<br />
2 4 6 8<br />
3 6 9 12<br />
v Die Matrix wird <strong>in</strong> Java folgendermaßen<br />
deklariert, <strong>in</strong>stantiiert <strong>und</strong> besetzt:<br />
<strong>in</strong>t[][] matrix = new <strong>in</strong>t[3][4];<br />
for (<strong>in</strong>t row = 0; row < 3; row++)<br />
for (<strong>in</strong>t col = 0; col < 4; col++)<br />
matrix[row][col] = (row+1) * (col+1);<br />
v Die entstehenden Reihungsobjekte lassen sich so veranschaulichen:<br />
matrix:<br />
3 6 9 12<br />
2 4 6 8<br />
1 2 3 4<br />
Das Element<br />
matrix[2][2]<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 23
mehrdimensionale <strong>Reihungen</strong> (cont‘d)<br />
v Dasselbe Ergebnis bekommt man, wenn man <strong>die</strong> 3 Zeilen e<strong>in</strong>zeln<br />
<strong>in</strong>stantiiert:<br />
<strong>in</strong>t[][] matrix;<br />
= new <strong>in</strong>t[3][];<br />
for (<strong>in</strong>t row = 0; row < 3; row++){<br />
matrix[row] = new <strong>in</strong>t[4];<br />
} for (<strong>in</strong>t col = 0; col < 4; col++)<br />
matrix[row][col] = (row+1) * (col+1);<br />
}<br />
matrix:<br />
3 6 9 12<br />
2 4 6 8<br />
1 2 3 4<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 24
Dreiecksmatrizen<br />
v Wenn <strong>die</strong> Zeilen 2-dimensionaler <strong>Reihungen</strong> e<strong>in</strong>zeln <strong>in</strong>stantiiert werden<br />
können, müssen sie auch nicht gleiche Länge haben.<br />
v Damit lassen sich z.B. Dreiecksmatrizen darstellen:<br />
<strong>in</strong>t[][] dreieck = new <strong>in</strong>t[3][];<br />
dreieck[0] = new <strong>in</strong>t[1];<br />
dreieck[1] = new <strong>in</strong>t[2];<br />
dreieck[2] = new <strong>in</strong>t[3];<br />
dreieck:<br />
0 0 0<br />
0<br />
0 0<br />
0 0<br />
0 0 0<br />
0<br />
Das Element<br />
dreieck[2][0]<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 25
2-dimensionale <strong>Reihungen</strong><br />
Motivation: Berechne <strong>die</strong> durchschnittliche monatliche<br />
Regenmenge <strong>in</strong> München.<br />
Mit e<strong>in</strong>er 1-dimensionalen Reihung wäre das möglich, aber sehr<br />
kompliziert:<br />
double[] ra<strong>in</strong>fall = new double[365];<br />
E<strong>in</strong>e 2-dimensionale Reihung ist e<strong>in</strong>e Reihung von <strong>Reihungen</strong> (an<br />
array of arrays) ist besser geeignet.<br />
Die erste Reihung s<strong>in</strong>d <strong>die</strong> 12 Monate, <strong>in</strong>diziert von 0 bis 11.<br />
Jeder Monat ist wieder e<strong>in</strong>e Reihung von 31 Tagen, <strong>in</strong>diziert von 0<br />
bis 30.<br />
double[][] ra<strong>in</strong>fall = new double[12][31];<br />
Monats<strong>in</strong>dex<br />
Tages<strong>in</strong>dex<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 26
E<strong>in</strong>e 2-D-Repräsentation<br />
Der Regenfall am 3. Januar ist mit <strong>die</strong>ser Repräsentation<br />
ra<strong>in</strong>fall[0][2] (schlechte Lesbarkeit durch Null-Indizierung).<br />
Wir können <strong>die</strong> Lesbarkeit erhöhen, <strong>in</strong>dem wir e<strong>in</strong>e extra Reihe <strong>und</strong><br />
Spalte erlauben <strong>und</strong> <strong>die</strong> 0-Indizes ignorieren:<br />
Wir ignorieren<br />
<strong>die</strong>se Spalte<br />
double[][] ra<strong>in</strong>fall = new double[13][32];<br />
.<br />
.<br />
.<br />
0,0 0,1 0,2 0,3 ... 0,29 0,30 0,31<br />
1,0 1,1 1,2 1,3 ... 1,29 1,30 1,31 Januar<br />
2,0 2,1 2,2 2,3 ... 2,29 2,30 2,31 Februar<br />
11,0 11,1 11,2 11,3 ... 11,29 11,30 11,31 November<br />
12,0 12,1 12,2 12,3 ... 12,29 12,30 12,31 Dezember<br />
Wir ignorieren <strong>die</strong>se Reihe<br />
Regenfall am 3. Januar<br />
ist jetzt ra<strong>in</strong>fall[1][3]<br />
ra<strong>in</strong>fall[1][5] = 1.15; // Regen für 5. Januar<br />
ra<strong>in</strong>fall[13][32] = 0.15 ; // Reihe <strong>und</strong> Spalte gibt es nicht!<br />
ra<strong>in</strong>fall[11][32] = 1.3; // 32. Spalte gibt es nicht!<br />
ra<strong>in</strong>fall[13][30] = 0.74; // 13. Reihe gibt es nicht!<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 27
Initialisierung e<strong>in</strong>er 2-dimensionalen Reihung <strong>in</strong><br />
e<strong>in</strong>er Methode<br />
Wir benutzen 2 geschachtelte Schleifen, um <strong>die</strong> Reihung zu<br />
<strong>in</strong>itialisieren:<br />
/**<br />
* Initialisiert e<strong>in</strong>e 2-D Reihung<br />
* Vorbed<strong>in</strong>gung: ra<strong>in</strong> ist nicht null<br />
* Nachbed<strong>in</strong>gung: ra<strong>in</strong>[x][y] == 0.0 für alle x,y <strong>in</strong> der Reihung<br />
*/<br />
public void <strong>in</strong>itRa<strong>in</strong>(double[][] ra<strong>in</strong>) {<br />
for (<strong>in</strong>t month = 1; month < ra<strong>in</strong>.length; month++)<br />
for (<strong>in</strong>t day = 1; day < ra<strong>in</strong>[month].length; day++)<br />
ra<strong>in</strong>[month][day] = 0.0;<br />
} // <strong>in</strong>itRa<strong>in</strong>()<br />
Methodenaufruf: Übergibt den Namen der Reihung an <strong>die</strong><br />
Methode:<br />
Die 2-D Reihung als<br />
formaler Parameter<br />
Zwei geschachtelte<br />
Zählschleifen, <strong>die</strong><br />
12 x 31 iterieren<br />
double[][] ra<strong>in</strong>fall = new double[13][32];<br />
<strong>in</strong>itRa<strong>in</strong>(ra<strong>in</strong>fall); // Beispiel e<strong>in</strong>es Methodenaufrufs<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 28
Berechnung des durchschnittlichen täglichen Regens<br />
public double avgDailyRa<strong>in</strong>(double[][] ra<strong>in</strong>) {<br />
double total = 0.0;<br />
for (<strong>in</strong>t month = 1; month < ra<strong>in</strong>.length; month++)<br />
for (<strong>in</strong>t day = 1; day < ra<strong>in</strong>[month].length; day++)<br />
total += ra<strong>in</strong>[month][day];<br />
return total/365;<br />
}<br />
System.out.pr<strong>in</strong>tln("Täglicher Regen: " + avgDailyRa<strong>in</strong>(ra<strong>in</strong>fall));<br />
Methodenaufruf <strong>in</strong>nerhalb e<strong>in</strong>er<br />
Druckanweisung.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 29
Berechnung des durchschnittlichen monatlichen Regens<br />
public double avgRa<strong>in</strong>ForMonth(double[][] ra<strong>in</strong>, <strong>in</strong>t month, <strong>in</strong>t nDays)<br />
{<br />
double total = 0.0;<br />
for (<strong>in</strong>t day = 1; day
<strong>Reihungen</strong> <strong>und</strong> Reihungswerte als Parametertypen<br />
Der Typ des aktuellen Parameters bei e<strong>in</strong>em Methodenaufruf muss<br />
denselben Typ wie der formale Parameter <strong>in</strong> der Methodendef<strong>in</strong>ition haben.<br />
Dies gilt für alle Parameter e<strong>in</strong>schließlich <strong>Reihungen</strong>:<br />
double<br />
double[]<br />
double[][]<br />
ra<strong>in</strong>fall[1][14]: Regenfall vom 14. Januar<br />
ra<strong>in</strong>fall[3]: 1-D-Reihung mit März-Daten<br />
ra<strong>in</strong>fall: Die gesamte 2-D-Reihung<br />
0<br />
1<br />
2<br />
.<br />
.<br />
.<br />
10<br />
11<br />
12<br />
13<br />
0 1 2 ... 31<br />
…...<br />
1.14<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 31<br />
J<br />
F<br />
M<br />
A<br />
M<br />
J<br />
…...<br />
O<br />
N<br />
D
Multidimensionale <strong>Reihungen</strong><br />
E<strong>in</strong>e 3-dimensionale Reihung kann man für <strong>die</strong> Messung von<br />
Regenfällen über mehrere Jahre benutzen.<br />
0<br />
1<br />
2<br />
.<br />
.<br />
.<br />
11<br />
12<br />
13<br />
0 1 2 ... year 0<br />
31<br />
0<br />
1<br />
2<br />
.<br />
.<br />
.<br />
11<br />
12<br />
13<br />
0 1 2 ... year 1<br />
J 31<br />
F<br />
0 1 2 ... year 2<br />
J 31<br />
0<br />
M<br />
F<br />
1<br />
A<br />
M<br />
2<br />
M<br />
A<br />
.<br />
J<br />
M<br />
.<br />
J<br />
J<br />
.<br />
A<br />
J<br />
S<br />
A<br />
O<br />
S<br />
N<br />
O<br />
D<br />
N<br />
11<br />
D<br />
12<br />
13<br />
J<br />
F<br />
M<br />
A<br />
M<br />
J<br />
J<br />
A<br />
S<br />
O<br />
N<br />
D<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 32
E<strong>in</strong>e 3-D-Reihung<br />
v Deklaration der Reihung:<br />
f<strong>in</strong>al <strong>in</strong>t NYEARS = 10;<br />
f<strong>in</strong>al <strong>in</strong>t NMONTHS = 13;<br />
f<strong>in</strong>al <strong>in</strong>t NDAYS = 32;<br />
double[][][] ra<strong>in</strong>fall = new double[NYEARS][NMONTHS][NDAYS];<br />
Initialisierung mit 3 geschachtelten Schleifen:<br />
for (<strong>in</strong>t year = 1; year < ra<strong>in</strong>fall.length; year++) {<br />
for (<strong>in</strong>t month = 1; month < ra<strong>in</strong>fall[year].length; month++) {<br />
for (<strong>in</strong>t day = 1; day < ra<strong>in</strong>fall[year][month].length; day++) {<br />
ra<strong>in</strong>fall[year][month][day] = 0.0;<br />
}<br />
}<br />
}<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 33
Initialisierung von <strong>Reihungen</strong><br />
v Bei kle<strong>in</strong>en <strong>Reihungen</strong>, kann man e<strong>in</strong>en Initialisierungsausdruck<br />
(<strong>in</strong>itializer expression) für <strong>die</strong> Zuweisung von Anfangswerten<br />
verwenden:<br />
2 x 3 Reihung<br />
von <strong>in</strong>t-Werten<br />
Initialisierungsausdruck<br />
<strong>in</strong>t[][] a = { {1, 2, 3}, {4, 5, 6} };<br />
2 x 2 Reihung char [][] c = { {'a', 'b'}, {'c', 'd'} };<br />
von char-Werten.<br />
double [][][] d ={ { {1.0, 2.0}, {3.0, 4.0} },<br />
{ {5.0, 6.0}, {7.0, 8.0} },<br />
{ {9.0, 10.0}, {11.0, 12.0}}<br />
};<br />
3 x 2 x 2 Reihung<br />
von double-Werten.<br />
In Java kann jede Teilreihung e<strong>in</strong>er mehr-dimensionalen Reihung<br />
e<strong>in</strong>e unterschiedliche Länge haben (siehe Dreiecksmatrix Beispiel )!<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 34
Dynamische <strong>Reihungen</strong>: java.util.Vector<br />
v Reguläre <strong>Reihungen</strong> s<strong>in</strong>d auf <strong>die</strong> zum Zeitpunkt der Initialisierung<br />
(statisch) vere<strong>in</strong>barte Größe beschränkt.<br />
Sie können später nicht mehr wachsen oder kle<strong>in</strong>er werden.<br />
v Die java.util.Vector Klasse implementiert e<strong>in</strong>e Reihung von Objekten<br />
(ke<strong>in</strong>e Gr<strong>und</strong>typwerte als Elemente!), <strong>die</strong> auch nach der Initialisierung<br />
(dynamisch) wachsen kann.<br />
public class Vector {<br />
public Vector(<strong>in</strong>t size);<br />
public Vector();<br />
// Konstruktor: Array mit Anfangsgröße<br />
// Konstruktor: Array ohne Anfangsgröße<br />
}<br />
public void addElement(Object obj);<br />
public Object elementAt(<strong>in</strong>t <strong>in</strong>dex);<br />
// Füge obj zum Array dazu<br />
// Hole das bei <strong>in</strong>dex<br />
// gespeicherte Element<br />
public void <strong>in</strong>sertElementAt(Object obj, <strong>in</strong>t <strong>in</strong>dex); // Speicher obj bei<br />
// <strong>in</strong>dex<br />
public <strong>in</strong>t <strong>in</strong>dexOf(Object obj); // Ermittle <strong>in</strong>dex von obj<br />
public void removeElementAt(<strong>in</strong>t <strong>in</strong>dex); // Entferne Element bei <strong>in</strong>dex<br />
public <strong>in</strong>t size(); // Länge des dynamischen Arrays<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 35
Sortierte <strong>Reihungen</strong><br />
v <strong>Reihungen</strong> <strong>die</strong>nen dazu, große Datenmengen zu verwalten.<br />
v Große Datenmengen lassen sich jedoch nicht effizient verwalten,<br />
wenn sie nicht sortiert vorliegen<br />
– Beispiel: Suche nach e<strong>in</strong>em Wort <strong>in</strong> e<strong>in</strong>em Roman vs. Suche<br />
nach e<strong>in</strong>em Wort <strong>in</strong> e<strong>in</strong>em Lexikon<br />
v Voraussetzung, dass man Daten sortieren kann, ist, dass auf dem<br />
Datentyp e<strong>in</strong>e Ordnung def<strong>in</strong>iert ist.<br />
v Programm für den Rest <strong>die</strong>ses Vorlesungsblocks:<br />
– Formale Def<strong>in</strong>ition von Relationen <strong>und</strong> unterschiedlichen<br />
Ordnungen (nach Goos)<br />
– Erste Algorithmen, um <strong>Reihungen</strong> zu sortieren<br />
– E<strong>in</strong> schneller Algorithmus, um <strong>in</strong> sortierten <strong>Reihungen</strong> Elemente<br />
zu f<strong>in</strong>den<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 36
Def<strong>in</strong>ition Relation<br />
v Gegeben seien zwei Mengen M <strong>und</strong> N.<br />
– Die Menge aller Paare (a, b) mit a aus M <strong>und</strong> b aus N heißt<br />
kartesisches Produkt von M <strong>und</strong> N.<br />
– <strong>in</strong> Zeichen: M ¥ N = def { (a, b) | a Œ M Ÿ b Œ N }<br />
v E<strong>in</strong>e (zweistellige) Relation R zwischen den Mengen M <strong>und</strong> N ist e<strong>in</strong>e<br />
Teilmenge des kartesischen Produkts:<br />
– R Õ M ¥ N<br />
– Statt (a,b) Œ R schreiben wir oft a R b (Infix-Schreibweise) <strong>und</strong><br />
sprechen „a steht <strong>in</strong> Relation R zu b“.<br />
v Falls M <strong>und</strong> N <strong>die</strong>selbe Menge s<strong>in</strong>d, d.h. falls gilt R Õ M ¥ M, dann<br />
nennen wir R auch e<strong>in</strong>e (zweistellige) Relation über M.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 37
Eigenschaften von Relationen über M<br />
E<strong>in</strong>e zweistellige Relation R über M (d.h. R Õ M ¥ M)<br />
v heißt reflexiv, wenn für alle a Œ M gilt: a R a<br />
– Beispiele: =, £ <strong>und</strong> Õ s<strong>in</strong>d reflexiv, < <strong>und</strong> Ã s<strong>in</strong>d es nicht.<br />
v heißt irreflexiv, wenn für ke<strong>in</strong> a Œ M gilt: a R a<br />
– Beispiele: < <strong>und</strong> Ã s<strong>in</strong>d irreflexiv, =, £ <strong>und</strong> Õ s<strong>in</strong>d es nicht.<br />
v heißt symmetrisch, wenn aus a R b folgt b R a<br />
– Beispiele: = ist symmetrisch,
Äquivalenzrelation <strong>und</strong> Ordnungen<br />
E<strong>in</strong>e zweistellige Relation R über M (d.h. R Õ M ¥ M)<br />
v heißt Äquivalenzrelation, wenn sie reflexiv, symmetrisch <strong>und</strong> transitiv<br />
ist;<br />
– Beispiele: = ist Äquivalenzrelation,
Sortieralgorithmus<br />
Algorithmus:<br />
1. Wandere über alle Elemente der Reihung, <strong>und</strong> zwar N-1 mal ("Phasen")<br />
2. Vergleiche <strong>die</strong> Nachbarelemente <strong>in</strong> der Reihung (Vergleich: N-1 Paare)<br />
3. Falls das kle<strong>in</strong>er <strong>in</strong>dizierte Element größer ist als das größer <strong>in</strong>dizierte Element<br />
4. Vertausche <strong>die</strong> beiden Elemente<br />
21 20 27 24 19 // Die unsortierte Reihung<br />
[20 21] 27 24 19 // Anfang Phase 1: Vergleiche Nachbarelemente<br />
20 [21 27] 24 19 // Vertausche,falls notwendig,geh weiter<br />
20 21 [24 27] 19 // Vertausche,falls notwendig,geh weiter<br />
20 21 24 [19 27]<br />
20 21 24 19 |27 // Ende Phase 1: 27 ist jetzt an der Spitze<br />
[20 21] 24 19 27 // Anfang Phase 2<br />
…<br />
20 19 21 |24 27 // Ende Phase 2: 24 hat jetzt se<strong>in</strong>en Platz<br />
….<br />
|19 20 21 24 27 // End Phase 4: Das ganze Feld ist sortiert<br />
Seifenblasen-Algorithmus (Bubblesort algorithm):<br />
Bei jeder R<strong>und</strong>e (auch Phase genannt) durch <strong>die</strong> Reihung lassen wir das<br />
größte noch nicht sortierte Element ans Ende "blubbern".<br />
Für e<strong>in</strong> Feld mit N Elementen werden N-1 Phasen benötigt.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 40
Die Idee h<strong>in</strong>ter dem Bubblesort<br />
Swap: 0<br />
Comp: 0<br />
Swap: 0<br />
Comp:1<br />
Swap:1<br />
Comp:2<br />
Swaps:25 Swaps:8 Swaps:9<br />
Comp: 45<br />
Comp:10 9<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 42
Wie vertauschen wir 2 Elemente <strong>in</strong> e<strong>in</strong>er Reihung?<br />
Beispiel: Nehmen wir an, wir haben <strong>die</strong> Reihung arr mit der<br />
Belegung: 1 4 2 8<br />
Wir wollen jetzt 4 and 2 vertauschen. Sei pair der Index <strong>in</strong> der<br />
Reihung, wir setzen also pair = 2; Los geht's:<br />
arr[pair-1] = arr[pair];<br />
arr[pair] = arr[pair-1];<br />
Wir bekommen: 1 2 2 8<br />
So e<strong>in</strong>fach geht es also nicht.<br />
Der Trick: E<strong>in</strong>e temporäre Variable muss deklariert werden, wenn man<br />
<strong>die</strong> Werte von zwei Variablen vertauschen will:<br />
<strong>in</strong>t temp = arr[pair-1];<br />
Wir erwarten: 1 2 4 8<br />
// Speichere den ersten Wert <strong>in</strong> temp<br />
arr[pair-1] = arr[pair]; // Überschreibe den ersten Wert mit<br />
// dem zweiten Wert<br />
arr[pair] = temp; // Überschreibe den zweiten Wert mit<br />
// temp (das den ersten Wert<br />
Ergebnis: 1 2 4 8<br />
// zwischengespeichert hat)!<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 43
Java-Implementation von Bubblesort mit Tausch<br />
<strong>in</strong>t[] arr = { 1, 4, 2, 8};<br />
// E<strong>in</strong>e vor<strong>in</strong>itialisierte Reihung von Werten<br />
for (<strong>in</strong>t pass = 1; pass < arr.length; pass++) {<br />
// Für jede R<strong>und</strong>e<br />
for (<strong>in</strong>t pair = 1; pair arr[pair]) { // Vergleiche <strong>die</strong> Werte<br />
// <strong>und</strong> vertausche, falls<br />
// notwendig<br />
<strong>in</strong>t temp = arr[pair-1]; // Speichere den ersten Wert <strong>in</strong> temp<br />
arr[pair-1] = arr[pair]; // Überschreibe den ersten Wert mit<br />
// dem zweiten Wert<br />
arr[pair] = temp; // Überschreibe den zweiten Wert mit<br />
// temp (das den ersten Wert<br />
// zwischengespeichert hat)!<br />
} // Ende if<br />
} // Ende for pair<br />
} // Ende for pass<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 44
Implementation von bubbleSort() als Dienst<br />
Parameter vom Typ Array s<strong>in</strong>d Referenzvariablen, d.h. <strong>die</strong><br />
Parameterübergabe erfolgt per Call-by-Reference: Änderungen, <strong>die</strong> an<br />
Reihungsvariablen <strong>in</strong> der Methode gemacht werden, s<strong>in</strong>d außerhalb der<br />
Methode sichtbar.<br />
Der formale Parameter ist als Reihung<br />
(<strong>in</strong>t[] arr) spezifiziert<br />
/**<br />
* Ziel: Sortiere <strong>die</strong> Werte von arr <strong>in</strong> aufsteigender Reihenfolge<br />
* Vorbed<strong>in</strong>gung: arr ist nicht null.<br />
* Nachbed<strong>in</strong>gung: Die Werte arr[0]...arr[arr.length-1] s<strong>in</strong>d <strong>in</strong><br />
* aufsteigender Reihenfolge sortiert.<br />
*/<br />
public void bubbleSort(<strong>in</strong>t[] arr) {<br />
for (<strong>in</strong>t pass = 1; pass < arr.length; pass++)<br />
Beim Methodenaufruf wird nur der Name<br />
des aktuellen Parameters benötikz<br />
// Für jede R<strong>und</strong>e<br />
for (<strong>in</strong>t pair = 1; pair < arr.length; pair++) // Für jedes Paar<br />
if (arr[pair-1] > arr[pair]) { // Vergleiche <strong>die</strong> Werte<br />
<strong>in</strong>t temp = arr[pair-1]; // <strong>und</strong> vertausche, falls<br />
arr[pair-1] = arr[pair]; // notwendig<br />
arr[pair] = temp;<br />
Aufrufendes Programm:<br />
} // if<br />
<strong>in</strong>t[] myArr = {21, 20, 27, 24, 19};<br />
} // bubbleSort()<br />
bubbleSort(myArr);<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 45
Aufruf des "Dienstes" Bubblesort<br />
public class Sort {<br />
public void pr<strong>in</strong>t(<strong>in</strong>t[] arr) {<br />
for (<strong>in</strong>t k = 0; k < arr.length; k++) // Für jedes Element<br />
System.out.pr<strong>in</strong>t( arr[k] + " \t "); // Drucke es<br />
System.out.pr<strong>in</strong>tln();<br />
} // pr<strong>in</strong>t()<br />
public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) {<br />
<strong>in</strong>t[] myArr = { 21, 20, 27, 24, 19 };<br />
Sort sorter = new Sort();<br />
sorter.pr<strong>in</strong>t(myArr);<br />
sorter.bubbleSort(myArr);<br />
sorter.pr<strong>in</strong>t(myArr);<br />
} // ma<strong>in</strong>()<br />
} // Sort public void bubbleSort(<strong>in</strong>t[] arr) {<br />
for (<strong>in</strong>t pass = 1; pass < arr.length; pass++)<br />
for (<strong>in</strong>t pair = 1; pair < arr.length;<br />
pair++)<br />
if (arr[pair-1] > arr[pair]) {<br />
<strong>in</strong>t temp = arr[pair-1];<br />
arr[pair-1] = arr[pair];<br />
arr[pair] = temp;<br />
} // if<br />
} // bubbleSort()<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 46
Bubblesort kann <strong>in</strong> 4 Zeilen geschrieben werden<br />
private void swap(<strong>in</strong>t one, <strong>in</strong>t two, <strong>in</strong>t[] arr) {<br />
<strong>in</strong>t temp = arr[one]; // Zwischenspeicher für arr[one]<br />
arr[one] = arr[two];<br />
arr[two] = temp;<br />
}<br />
// In Swap übergebe ich <strong>die</strong> Array-Indizes,<br />
// nicht <strong>die</strong> Array-Elementwerte<br />
public void bubbleSort(<strong>in</strong>t[] arr) {<br />
for (<strong>in</strong>t pass = 1; pass < arr.length; pass++) // Für jede R<strong>und</strong>e<br />
for (<strong>in</strong>t pair = 1; pair < arr.length; pair++)// Für jedes Paar<br />
if (arr[pair-1] > arr[pair] // Vergleiche <strong>die</strong> Werte<br />
swap(pair-1, pair, arr); // Swap, falls notwendig<br />
}<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 47
Komplexität von Algorithmen<br />
v Bubblesort lässt sich schnell implementieren, arbeitet aber sehr langsam,<br />
vor allem, wenn <strong>die</strong> Anzahl der Elemente größer wird.<br />
v Es gibt schnellere Sortieralgorithmen als Bubblesort.<br />
– Selectionsort, Insertionsort, Quicksort, Mergesort<br />
v Wenn wir verschiedene Algorithmen haben, ist es nützlich, <strong>die</strong>se<br />
Algorithmen bezüglich ihrer Kosten zu vergleichen.<br />
v Arten von Kosten:<br />
– Programmieraufwand (sehr ger<strong>in</strong>g bei Bubblesort)<br />
– Ausbildungsaufwand für Programmierer<br />
– Anschaffungskosten für Rechner <strong>und</strong> Software<br />
– Rechenzeit, Speicherplatzbedarf<br />
v Beim Vergleichen von Algorithmen konzentrieren wir uns auf<br />
Rechenzeit <strong>und</strong> Speicherplatzbedarf <strong>und</strong> vernachlässigen Faktoren, <strong>die</strong><br />
von der Leistungsfähigkeit des Rechners oder der Programmiersprache<br />
abhängen.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 48
2 Arten von Komplexität, 3 Fallunterscheidungen<br />
v Zeitkomplexität: Wieviele Schritte muss e<strong>in</strong> Algorithmus durchführen,<br />
um N E<strong>in</strong>gabedaten zu verarbeiten?<br />
v Platzkomplexität: Wieviel Speicherplatz braucht e<strong>in</strong> Algorithmus, um<br />
N E<strong>in</strong>gabedaten zu verarbeiten?<br />
v Im folgenden beschränken wir uns auf <strong>die</strong> Zeitkomplexität.<br />
v Wir müssen trotzdem folgende Fälle unterscheiden:<br />
– Anzahl der Schritte im schlechtesten Fall (worst case)<br />
– Beispiel: Die Reihung ist völlig unsortiert<br />
– Anzahl der Schritte im besten Fall (best case)<br />
– Beispiel: Die Reihung ist bereits sortiert<br />
– Anzahl der Schritte im durchschnittlichen Fall (average case)<br />
– Beispiel: Die Reihung ist zur Hälfte sortiert.<br />
v Wenn wir von nun an den Begriff Komplexität alle<strong>in</strong> verwenden,<br />
me<strong>in</strong>en wir gewöhnlich Zeitkomplexität im schlechtesten Fall.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 49
E<strong>in</strong>flussfaktoren für Zeitkomplexität<br />
v Wir nehmen an, dass nur Zuweisungen, Vergleiche,<br />
Inkrementierungen <strong>und</strong> Multiplikationen Zeit kosten.<br />
v Wir nehmen an, dass <strong>die</strong> Deklaration von Variablen <strong>und</strong> Allokation<br />
von Speicherplatz ke<strong>in</strong>e Zeit kostet.<br />
v Wir bestimmen deshalb <strong>in</strong> Abhängigkeit von der E<strong>in</strong>gabe n nur<br />
– Z(n): Die Anzahl der Zuweisungen<br />
– V(n): Die Anzahl der Vergleiche<br />
– M(n): Die Anzahl der Multiplikationen<br />
– I(n): Die Anzahl der Inkrementierungen<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 51
Komplexitätsüberlegungen für den Bubblesort:<br />
v Wir haben ke<strong>in</strong>e Multiplikationen.<br />
v Die Anzahl der Inkrementierungen der Schleifenvariablen <strong>und</strong><br />
Vergleiche zur Schleifenterm<strong>in</strong>ierung vernachlässigen wir hier.<br />
v Die Komplexität von Bubblesort wird dann durch 2 Arten von<br />
Operationen bestimmt:<br />
– V(n) = Anzahl der Vergleiche zwischen Elementen<br />
– T(n) = Anzahl der Tauschoperationen (swap) von Elementen<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 52
Komplexitätsüberlegungen für Bubblesort<br />
v Anzahl der Vergleichsoperationen V:<br />
– Bei n =10 s<strong>in</strong>d <strong>in</strong> der ersten R<strong>und</strong>e 9 Vergleiche, <strong>in</strong> der zweiten<br />
R<strong>und</strong>e 8 Vergleiche, usw., bis zu 1 Vergleich <strong>in</strong> der letzten R<strong>und</strong>e:<br />
9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 = 45<br />
– Allgeme<strong>in</strong> V(n) = (n-1) + (n-2) + …. 1 = n*(n-1)/2<br />
– Bei großem n ist n*(n-1)/2 ungefähr n 2 /2, also<br />
u V(n) ~ n 2 /2<br />
v Anzahl der Tauschoperationen:<br />
– E<strong>in</strong> Tausch f<strong>in</strong>det nur statt, wenn das erste Element größer als das<br />
zweite Element ist. E<strong>in</strong> Tausch T besteht aus 3 Zuweisungen Z<br />
– Wenn <strong>die</strong> Datenverteilung zufällig ist, dann können wir annehmen,<br />
dass e<strong>in</strong> Tausch ungefähr <strong>in</strong> der Hälfte aller Fälle notwendig ist.<br />
u T(n) ~ n 2 /4<br />
u Z(n) ~ 3 * n 2 /4<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 53
Komplexität des Bubblesorts 11/20/03<br />
v Anzahl aller Operationen <strong>in</strong> Bubblesort ~ n 2 /2 + 3*n 2 /4<br />
– Die Anzahl der Vergleichsoperationen <strong>und</strong> Zuweisungen ist also<br />
proportional zu n 2.<br />
v Bei asymptotischen Komplexitätsberechnungen können wir <strong>die</strong><br />
Konstanten weglassen.<br />
v Bubblesort hat somit <strong>die</strong> Komplexität O( n 2 ).<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 54
Allgeme<strong>in</strong>e Beobachtungen zur Komplexität<br />
v Geschachtelte Schleifen haben oft Laufzeitkomplexität O( n 2 ):<br />
– Die äußere Schleife exekutiert n mal, <strong>die</strong> <strong>in</strong>nere für jeden Zyklus<br />
der äußeren Schleife n mal (oder vielleicht n divi<strong>die</strong>rt durch e<strong>in</strong>e<br />
Konstante).<br />
Das ergibt dann ungefähr n*n Operationen, oder O( n 2 ).<br />
v Weitere e<strong>in</strong>fache Sortieralgorithmen mit O( n 2 )-Komplexität:<br />
– Selectionsort<br />
– Insertionsort<br />
v O( n 2 ) ist für das <strong>Sortieren</strong> e<strong>in</strong>e schlechte Komplexität, wenn <strong>die</strong><br />
Anzahl der Elemente sehr groß ist. In <strong>die</strong>sem Fall brauchen wir<br />
Algorithmen, <strong>die</strong> e<strong>in</strong>e bessere Laufzeitkomplexität haben.<br />
v Schnellere Sortieralgorithmen mit O(n*log n)<br />
u Mergesort<br />
u Quicksort<br />
Heute<br />
nach <strong>Kapitel</strong> funktionale Programmierung<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 55
Komplexität: Theorie <strong>und</strong> Praxis<br />
v Die Ordnung von f, geschrieben O(f(n)) ist e<strong>in</strong>e Abschätzung für<br />
das Wachstum von Funktionen (z.b. für <strong>die</strong> Laufzeit e<strong>in</strong>es<br />
Algorithmus)<br />
– d.h. <strong>die</strong> Komplexitätsüberlegungen gelten für den Fall n Æ µ<br />
v Das Laufzeitverhalten von zwei Algorithmen, auch wenn sie <strong>die</strong><br />
<strong>die</strong>selbe Laufzeitkomplexität haben, kann sehr wohl grosse<br />
Unterschiede bei praktischen Werten für <strong>die</strong> Anzahl der<br />
E<strong>in</strong>gabewerte zeigen.<br />
v Beispiel:<br />
– Verschiedene Implementationen für <strong>die</strong> Matrixmultiplikation<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 56
Beispiel: Matrixmultiplikation<br />
v Gr<strong>und</strong>idee des Algorithmus: Reihen mit Spalten multiplizieren<br />
v allgeme<strong>in</strong>:<br />
/* ijk */<br />
for (i = 0; i < n; i++) {<br />
for (j = 0; j < n; j++) {<br />
sum = 0.0;<br />
for (k = 0; k < n; k++)<br />
sum += a[i][k]*b[k][j];<br />
c[i][j] = sum;<br />
}<br />
}<br />
v Komplexität für Matrizenmultiplikation ist O(n 3 )<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 57
Zwei Algorithmen für <strong>die</strong> Matrixmultiplikation<br />
/* ijk */<br />
for (i = 0; i < n; i++) {<br />
for (j = 0; j < n; j++) {<br />
sum = 0.0;<br />
for (k = 0; k < n; k++)<br />
sum += A[i][k]*B[k][j];<br />
C[i][j] = sum;<br />
}<br />
}<br />
/* kij */<br />
for (k = 0; k < n; k++)<br />
for (i = 0; i < n; i++) {<br />
sum = 0.0;<br />
for (j = 0; j < n; j++)<br />
sum += A[i][k]*B[k][j];<br />
C[i][j] = sum;<br />
}<br />
}<br />
Ergeben <strong>die</strong> beiden Algorithmen dasselbe Resultat?<br />
Ja!<br />
Haben beide Algorithmen <strong>die</strong>selbe Laufzeitkomplexität?<br />
Ja!<br />
Wie sieht es mit der aktuellen Laufzeit aus?<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 58
Laufzeit der Implementation (Reihenfolge i-j-k)<br />
Zeit<br />
/* ijk */<br />
for (i = 0; i < n; i++) {<br />
for (j = 0; j < n; j++) {<br />
sum = 0.0;<br />
for (k = 0; k < n; k++)<br />
sum += A[i][k]*B[k][j];<br />
C[i][j] = sum;<br />
}<br />
}<br />
Grösse der<br />
Matrix<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 59
Alternative Implementation (Reihenfolge k-i-j)<br />
/* kij */<br />
for (k = 0; k < n; k++)<br />
for (i = 0; i < n; i++) {<br />
sum = 0.0;<br />
for (j = 0; j < n; j++)<br />
sum += A[i][k]*B[k][j];<br />
C[i][j] += sum;<br />
}<br />
}<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 60
Laufzeitverhalten von verschiedenen Implementationen<br />
jki<br />
kji<br />
ijk<br />
jik<br />
Warum s<strong>in</strong>d <strong>die</strong><br />
kij <strong>und</strong> ikj<br />
Implementationen<br />
so schnell?<br />
kij<br />
ikj<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 61
Interpretation der Ergebnisse<br />
v Trotz der gleichen Anzahl von Operationen <strong>in</strong> jedem Algorithmus<br />
sehen wir sehr unterschiedliche Laufzeiten<br />
– kij ist bis zu 3 mal schneller als kji bei gleicher Matrixgröße<br />
v Für Multiplikationen von kle<strong>in</strong>en Matrizen ist der Effekt nicht zu<br />
beobachten, sehr wohl aber bei großen Matrizen<br />
– Bei n = 400 braucht kij nur 2.5 sek, kji braucht 8 sek<br />
v Gr<strong>und</strong> für <strong>die</strong> unterschiedlichen Laufzeiten:<br />
– Größe des Prozessorcaches <strong>und</strong> des Speicherbedarfs der<br />
<strong>in</strong>neren Schleife<br />
v Lektion: Auch beim Programmieren mit höherer<br />
Programmiersprachen muss man <strong>die</strong> Rechnerarchitektur kennen.<br />
=> Technische <strong>Informatik</strong>, TGI Praktikum<br />
=> Mehr darüber auch im <strong>Kapitel</strong> über masch<strong>in</strong>ennahe<br />
Programmierung (Info II)<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 64
E<strong>in</strong> anderer Sortieralgorithmus:<br />
<strong>Sortieren</strong> nach Auswahl (Selectionsort)<br />
v Gr<strong>und</strong>pr<strong>in</strong>zip:<br />
– Partitioniere <strong>die</strong> Reihung <strong>in</strong> zwei Teilreihungen F <strong>und</strong> S.<br />
Solange es Elemente <strong>in</strong> der Reihung F gibt, f<strong>in</strong>de <strong>in</strong> F das kle<strong>in</strong>ste<br />
Element, <strong>und</strong> überführe es ans Ende der Reihung S.<br />
v Algorithmus für Selectionsort (<strong>in</strong> Pseudocode):<br />
1. Initialisierung: Setze S auf null<br />
2. Trivialfall: Wenn F == null, dann ist S das Ergebnis<br />
3. Reduktion:<br />
F<strong>in</strong>de das M<strong>in</strong>imum <strong>in</strong> F:<br />
a = select(F)<br />
Hänge a an das Ende von S: appendElem(S, a)<br />
Entferne a aus F: deleteElem(F, a)<br />
4. Iteration: Gehe nach 2<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 65
Gr<strong>und</strong>idee des Algorithmus<br />
S<br />
F<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 66
Selectionsort<br />
Animation<br />
public void selectionSort() {<br />
<strong>in</strong>t outer, <strong>in</strong>ner, m<strong>in</strong>;<br />
for(outer = 0; outer < nElems-1; outer++){ // Äussere Schleife<br />
m<strong>in</strong> = outer;<br />
// Bestimme Index des M<strong>in</strong>imums<br />
for(<strong>in</strong>ner = outer+1; <strong>in</strong>ner < nElems; <strong>in</strong>ner++){ // Innnere Schleife<br />
if(a[<strong>in</strong>ner] < a[m<strong>in</strong>]) // Wenn a[m<strong>in</strong>] größer ist,<br />
m<strong>in</strong> = <strong>in</strong>ner;<br />
// dann haben wir e<strong>in</strong> neues M<strong>in</strong><br />
}<br />
swap(outer, m<strong>in</strong>, a); // Vertausche <strong>die</strong> Elemente<br />
} // end for(outer)<br />
} // end selectionSort()<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 67
Komplexität von Selectionsort<br />
v Selectionsort führt <strong>die</strong>selbe Anzahl von Vergleichen aus wie<br />
Bubblesort.<br />
v Für großes n dom<strong>in</strong>ieren <strong>die</strong> Vergleichsoperationen, so dass auch<br />
Selectionsort <strong>die</strong> Komplexität O(n 2 ) hat.<br />
v Selectionsort führt im allgeme<strong>in</strong>en wesentlich weniger<br />
Tauschoperationen aus (e<strong>in</strong>e pro Durchlauf der äußeren Schleife).<br />
v Beispiel:<br />
– Für 100 Datenelemente werden 4950 Vergleiche benötigt, aber<br />
nur 100 Tauschoperationen.<br />
v Deshalb ist Selectionsort im allgeme<strong>in</strong>en schneller als Bubblesort.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 68
Noch e<strong>in</strong> Sortieralgorithmus: Insertionsort<br />
v Insertionsort beruht auf der Idee, dass e<strong>in</strong> Teil der Reihung bereits<br />
partiell sortiert ist.<br />
v Wir entnehmen uns e<strong>in</strong> Element aus der noch nicht sortierten<br />
Reihung <strong>und</strong> nennen es das „markierte Element“.<br />
v Wir sortieren dann das markierte Element an der Stelle im partiell<br />
sortierten Teil e<strong>in</strong>, wo es von der Größe her h<strong>in</strong>gehört.<br />
– Um das zu ermöglichen, müssen wir Platz für das markierte<br />
Element machen.<br />
– Wir tun <strong>die</strong>s, <strong>in</strong> dem wir e<strong>in</strong>ige bereits sortierte Elemente nach<br />
rechts schieben, <strong>und</strong> zwar <strong>die</strong>, <strong>die</strong> größer als das markierte<br />
Element s<strong>in</strong>d.<br />
– Um Platz für <strong>die</strong>se Verschiebung zu haben, nehmen wir das<br />
markierte Element temporär aus der Reihung (<strong>in</strong> e<strong>in</strong>e temporäre<br />
Variable).<br />
v Wir term<strong>in</strong>ieren den Sortiervorgang, wenn der nicht sortierte Teil der<br />
Reihung leer ist.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 69
Die Idee h<strong>in</strong>ter<br />
Insertionsort<br />
Animation<br />
Partiell sortiert<br />
M<br />
Partiell sortiert<br />
"leer"<br />
temp<br />
Partiell sortiert<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 70
Implementation von Insertionsort<br />
public void <strong>in</strong>sertionSort(double[] a) {<br />
<strong>in</strong>t <strong>in</strong>, out;<br />
}<br />
for (out = 1; out < nElems; out++) { // out ist <strong>in</strong>dex des<br />
// markierten Elements<br />
double temp = a[out]; // "entferne" markiertes Element<br />
<strong>in</strong> = out;<br />
// start das Verschieben:<br />
while(<strong>in</strong> > 0 && a[<strong>in</strong>-1] > temp) { // Solange Elemente<br />
// größer,<br />
a[<strong>in</strong>] = a[<strong>in</strong>-1]; // schiebe Elemente nach rechts<br />
<strong>in</strong> = <strong>in</strong>-1; // gehe e<strong>in</strong>e Position nach l<strong>in</strong>ks<br />
}<br />
a[<strong>in</strong>] = temp; // Setze das markierte Element e<strong>in</strong><br />
}<br />
Durchschnittliche Laufzeitkomplexität<br />
von Insertionsort<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 71
Wiederholung: E<strong>in</strong>flussfaktoren für<br />
Zeitkomplexität<br />
v Wir bestimmen <strong>in</strong> Abhängigkeit von der E<strong>in</strong>gabe n<br />
– Z(n): Die Anzahl der Zuweisungen<br />
– V(n): Die Anzahl der Vergleiche<br />
– M(n): Die Anzahl der Multiplikationen<br />
– I(n): Die Anzahl der Inkrementierungen<br />
v Wir unterscheiden folgende Fälle :<br />
– Anzahl der Schritte im schlechtesten Fall (worst case)<br />
– Beispiel: Die Reihung ist völlig unsortiert<br />
– Anzahl der Schritte im besten Fall (best case)<br />
– Beispiel: Die Reihung ist bereits sortiert<br />
– Anzahl der Schritte im durchschnittlichen Fall (average case)<br />
– Beispiel: Die Reihung ist zur Hälfte sortiert.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 72
Komplexität von Insertionsort (durchschnittlicher Fall)<br />
v In der ersten R<strong>und</strong>e wird nur e<strong>in</strong> Element verglichen, <strong>in</strong> der<br />
zweiten R<strong>und</strong>e höchstens zwei Elemente.<br />
v In der letzten R<strong>und</strong>e haben wir maximal n-1 Vergleiche:<br />
– V(n) = 1+2+3….+n-1= n*(n-1)/2<br />
v Im durchschnittlichen Fall werden höchstens <strong>die</strong> Hälfte der<br />
Elemente <strong>in</strong> jeder R<strong>und</strong>e vertauscht, also n*(n-1)/4<br />
v Für jeden Tausch brauchen wir 3 Operationen:<br />
– Z(n) ~ 3 * n 2 /4<br />
v Anzahl der Operationen <strong>in</strong> Insertionsort also ~ n 2 /4 + 3*n 2 /4<br />
v Insertionsort hat somit auch <strong>die</strong> Komplexität O( n 2 ).<br />
v Bei kle<strong>in</strong>em n ist Insertionsort zweimal schneller als Bubblesort<br />
(da weniger Kopien) <strong>und</strong> leicht schneller als Selectionsort.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 73
Vorteil von Insertionsort bei sortierten <strong>Reihungen</strong><br />
v Wenn <strong>die</strong> Daten sortiert s<strong>in</strong>d, wird <strong>die</strong> E<strong>in</strong>trittsbed<strong>in</strong>gung <strong>in</strong> <strong>die</strong><br />
While-Schleife (while(<strong>in</strong> > 0 && a[<strong>in</strong>-1] > temp))<br />
fast nie wahr.<br />
v In <strong>die</strong>sem Fall wird <strong>in</strong> der äußeren Schleife nur e<strong>in</strong>e Anweisung<br />
exekutiert.<br />
v Bei sortierten <strong>Reihungen</strong> ist <strong>die</strong> Komplexität von Insertionsort<br />
somit nur O(n).<br />
v Falls <strong>die</strong> Daten sortiert s<strong>in</strong>d, läuft Insertionsort also <strong>in</strong> O(n).<br />
Merken: Insertionsort ist e<strong>in</strong>e gute Sortiermethode, wenn <strong>die</strong> zu<br />
sortierende Reihung bereits weitgehend vorsortiert ist.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 74
Sequentieller Suchalgorithmus für <strong>Reihungen</strong><br />
Problem: Suche <strong>in</strong> e<strong>in</strong>er nichtsortierten Reihung a nach e<strong>in</strong>em<br />
bestimmten Wert key.<br />
Idee des Algorithmus: Da <strong>die</strong> Reihung a nicht sortiert ist, müssen<br />
wir e<strong>in</strong>e sogenannte sequentielle Suche durchführen.<br />
public <strong>in</strong>t sequentialSearch(<strong>in</strong>t[] a, <strong>in</strong>t key) {<br />
for (<strong>in</strong>t k = 0; k < a.length; k++)<br />
if (a[k] == key)<br />
return k;<br />
return -1; // Nicht gef<strong>und</strong>en<br />
} // sequentialSearch()<br />
Die Suche war nicht<br />
erfolgreich.<br />
Sobald der Wert gef<strong>und</strong>en ist,<br />
können wir zum Aufrufer<br />
zurückkehren.<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 76
Komplexität von sequentieller Suche<br />
v Die Suche nach e<strong>in</strong>em Element <strong>in</strong> e<strong>in</strong>er ungeordneten Reihung mit<br />
n Elementen ist<br />
– im schlechtesten Fall: V(n) = n<br />
– im durchschnittlichen Fall: V(n) = n/2<br />
– im besten Fall: V(n) = 1<br />
v Komplexität für sequentielle Suche: O(n)<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 77
Implementation von b<strong>in</strong>ärer Suche<br />
Algorithmus: low <strong>und</strong> high zeigen auf das erste <strong>und</strong> letzte Element<br />
der Teilreihung (subarray), <strong>und</strong> mid zeigt immer auf den derzeitigen<br />
Mittelpunkt <strong>in</strong> der Reihung oder Teilreihung.<br />
/**<br />
* Vorbed<strong>in</strong>gung: a ist aufsteigend sortierte Reihung von <strong>in</strong>t<br />
* Nachbed<strong>in</strong>gung: Ergebnis ist -1 oder k, wobei a[k] == key<br />
*/<br />
Wenn low > high, dann ist<br />
public <strong>in</strong>t b<strong>in</strong>arySearch(<strong>in</strong>t[] a, <strong>in</strong>t key) { der Schlüssel nicht <strong>in</strong> der<br />
<strong>in</strong>t low = 0; // Initialisierung<br />
Reihung.<br />
<strong>in</strong>t high = a.length - 1;<br />
while (low high: Suche erfolglos<br />
low bzw. high anpassen, um <strong>die</strong><br />
Reihung <strong>in</strong> 2 Hälften zu schneiden<br />
Code<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 79
Noch e<strong>in</strong> Beispiel<br />
Wir suchen nach Zahl 8<br />
Erste Iteration:<br />
key = 8;<br />
low = 0; high = 9;<br />
mid = 4;<br />
a[4] == 5<br />
Zweite Iteration:<br />
key = 8;<br />
low = 5; high = 9;<br />
mid = 7;<br />
a[7] == 8<br />
1 2 3 4<br />
public <strong>in</strong>t b<strong>in</strong>arySearch(<strong>in</strong>t[] a, <strong>in</strong>t key) {<br />
<strong>in</strong>t low = 0;<br />
<strong>in</strong>t high = a.length - 1;<br />
while (low
Komplexität von b<strong>in</strong>ärer Suche<br />
v L<strong>in</strong>eare Suche läuft auf<br />
beliebigen <strong>Reihungen</strong><br />
v B<strong>in</strong>äre Suche braucht e<strong>in</strong>e<br />
sortierte Reihung<br />
v Bei e<strong>in</strong>er Reihung von bis<br />
zu n Elementen brauchen<br />
wir höchstens log 2 (n)<br />
Vergleiche<br />
v Die Komplexität von<br />
b<strong>in</strong>ärer Suche für sortierte<br />
<strong>Reihungen</strong> ist also<br />
O(log 2 (n)).<br />
max. Anzahl von<br />
Elementen n<br />
<strong>in</strong> der Reihung<br />
1<br />
2<br />
4<br />
8<br />
16<br />
32<br />
64<br />
128<br />
256<br />
512<br />
513<br />
1024<br />
2<br />
log 2<br />
(n)<br />
max. Anzahl<br />
von Teilungen<br />
log 2<br />
(n)<br />
2 0<br />
0<br />
2 1<br />
1<br />
2 2<br />
2<br />
2 3<br />
3<br />
2 4<br />
4<br />
2 5<br />
5<br />
2 6<br />
6<br />
2 7<br />
7<br />
2 8<br />
8<br />
2 9<br />
9<br />
2 10<br />
10<br />
2 10 10<br />
Copyright 2003 Bernd Brügge, Christian Herzog E<strong>in</strong>führung <strong>in</strong> <strong>die</strong> <strong>Informatik</strong> I, TUM W<strong>in</strong>tersemester 2003/04 <strong>Kapitel</strong> 6, Folie 82