Übung: Deklarieren Sie ein entsprechendes Feld in Java! Programmierung mit Feldern OOPM, Ralf Lämmel
Einführendes Beispiel Eingabe: ein Feld von int-werten public static int sum(int[] a) { int result = 0; for (int i=0; i<a.length; i++) result = result + a[i]; return result; Zugriff auf einen Index des Feldes } Ausgabe: die Summe der Werte des Feldes (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau Siehe package data.vector 148
Was ist ein Feld? http://www.tholiger.de/landschaftenseite/original/feld.html Ein Feld ist eine Datenstruktur welche aus einer endlichen, geordneten Gruppe von Elementen des gleichen Typs besteht und auf die mit einem Index zugegriffen werden kann. Beispiele für die Anwendung: Vektoren, Matrizen Tabellen Zeichenketten... (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau 149
150 Feldzugriff ( subscript ) myarray 0 1 2 3 4 5 6 7 8 9 12 43 6 83 14-57 109 12 0 6 myarray[0] myarray[5] myarray[9]
151 Sprachkonstrukte (Deklaration) Deklaration von Variablen vom Feldtyp. int[] a; // Deklaration eines Zeigers auf ein Feld new int[5] // Ausdruck zur Speicheranforderung für ein Feld int[] a = new int[5]; // Kombination int[] a = new int[] {1,3,5,7,9}; // Initialisierung int[] a = {1,3,5,7,9}; // Initialisierung verkürzt
152 Sprachkonstrukte (Zugriff) Zugriff auf ein Element in einem Feld int x = a[5]; // Lesender Zugriff a[42] = 88; // Schreibender Zugriff Bestimmung der Größe eines Feldes a.length
153 Summierung der Elemente eines Feldes Beispiel Eingabe: {1,2,3,4} Ausgabe: 10
Summierung der Elemente eines Feldes public static int sum(int[] a) { int result = 0; for (int i=0; i<a.length; i++) Eingabe: ein Feld von int-werten result = result + a[i]; return result; Zugriff auf einen Index des Feldes } Ausgabe: die Summe der Werte des Feldes Siehe package data.vector (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau 154
155 Summierung der Elemente eines Feldes public static int sum(int[] a) { int result = 0; for (int i=0; i<a.length; i++) result += a[i]; return result; Kombinierte Addition und Zuweisung }
156 Testrahmen für Summierung public static void main(string[] args) { int[] a = new int[] {1,2,3,4}; System.out.println(sum(a)); // prints 10 }
157 Feldallokation und Feldgröße Platz für Feldelement muss angefordert werden ( new ). Feldgröße ist nicht Bestandteil des Typs. Die Feldgröße wird bei der Anforderung festgelegt.
158 Programmierfehler public static void main(string[] args) { int[] a; System.out.println(sum(a)); } Was passiert?
159 Programmierfehler public static void main(string[] args) { int[] a = null; System.out.println(sum(a)); } Was passiert?
160 Programmierfehler public static void main(string[] args) { int[] a = new int[] {}; System.out.println(sum(a)); } Was passiert?
161 Testen der Sortiertheit Beispiel 1: Eingabe: {1,2,3,4} Ausgabe: true Beispiel 2: Eingabe: {1,3,2,4} Ausgabe: false
162 Das Problem des Testens der Sortiertheit Eingabe: Ein Feld a mit n Elementen vom Typ t. Ausgabe: Ein Boolescher Wert: true: a[i-1] <= a[i] für alle i mit 1 <= i < n http://www.bambinipronto.com.au/ false: sonst
163 Probleme: Kontenverwaltung, Videokompression,... Programme: (Effektive) Problemlösungen Spezifikationen: ( Gute ) Problembeschreibungen Modelle: Abstraktionen von Problemlösungen u.a. Eingabe: Ein Feld a mit n Elementen vom Typ t. Ausgabe: Ist diese Problembeschreibung eine Spezifikation, ein Modell oder ein Programm? Ein Boolescher Wert: true: a[i-1] <= a[i] für alle i mit 1 <= i < n false: sonst
Sortiertheitstest public static boolean issorted(int[] a) { for (int i=1; i<a.length; i++) if (a[i-1] > a[i]) return false; // inversion found return true; // no inversion found } (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau Siehe package algorithm.search 164
165 Ausgabe eines Feldes Beispiel Eingabe: {1,2,3,4} Ausgabe: 1 2 3 4 (in der Standardausgabe )
Ausgabe eines Feldes public static void print(int[] a) { for (int i=0; i<a.length; i++) System.out.print(a[i] + " "); System.out.println(); } Eingabe: {1,2,3,4} Ausgabe: 1 2 3 4 (in der Standardausgabe ) (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau Siehe package data.vector 166
167 Der Ergebnistyp void void ist ein spezieller vordefinierter Typ. void ist formal ein Menge mit einem Element. Verwendung: Funkion berechnet keine Ergebnisse. Beispiele: Mutationen, Ausgaben
For-Each-Schleifen (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau 168
169 Programmierfehler mit For-Schleife public static void print(int[] a) { for (int i=0; i<=a.length; i++) System.out.print(a[i] + " "); System.out.println(); } Was ist das Problem?
170 Schleifen für Feldzugriff Herkömmliche Schleifen Verwendung von ganzzahligem Index Programmierung von Schleifenabbruch Dies resultiert in Fehlermöglichkeiten. Syntaxzucker für For-Each Schleifen Garantiert erschöpfende Iteration Sicherer, nicht-index-basierter Zugriff Einschränkung der Ausdruckskraft
Verwendung einer For-Each-Schleife public static void print(int[] a) { for (int x : a) System.out.print(x + " "); System.out.println(); } Was kann man mit dieser Art von Schleifenkonstruktion nicht erreichen (verglichen zur normalen For-Schleife)? (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau Siehe package data.vector 171
172 Vektoraddition Beipsiel Eingabe: - {1,2,3,4} - {11,9,7,5} Ausgabe: {12,11,10,9}
Vektoraddition public static int[] add(int[] v1, int[] v2) { int[] result = new int[v1.length]; for (int i=0; i<v1.length; i++) result[i] = v1[i] + v2[i]; return result; Wir ignorieren hier das Problem ungleicher Längen für v1 und v2. } (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau Siehe package data.vector 173
174 Umdrehen eines Feldes Beispiel Eingabe: {1,2,3,4} Ausgabe: {4,3,2,1}
175 Umdrehen eines Feldes public static void reverse(int[] a) { } int i = 0; int j = a.length - 1; while (i<j) { } int t = a[i]; a[i] = a[j]; a[j] = t; i++; j--; Man könnte sich auch eine Funktion vorstellen, welche das Eingabefeld nicht ändern sollte. (Siehe nächste Folie.)
176 Umdrehen eines Feldes (seiteneffektfreie Variante) public static int[] reverse(int[] a) { int[] b = new int[a.length]; int i = 0; int j = a.length - 1; while (i<a.length) { b[i] = a[j]; i++; j--; } return b; }
177 Umdrehen eines Feldes (kompaktere, seiteneffektfreie Variante) public static int[] reverse(int[] a) { int[] b = new int[a.length]; int i = 0; int j = a.length - 1; while (i<a.length) b[i++] = a[j--]; return b; } Verwendung von Postfix ist essentiell!
178 Post-/prefixoperatoren ++ und -- Verwendung Einsparung von extra Anweisungssequenzen Formen x++ x-- ++x inkrementiert x nach der Verwendung von x. dekrementiert x nach der Verwendung von x. inkrementiert x vor der Verwendung von x. --x dekrementiert x vor der Verwendung von x.
179 Das Such-Problem Eingabe: Ein Feld a mit n Elementen vom Typ t. Ein Wert x vom Typ t. Ausgabe: Ein Boolescher Wert: true: Es gibt ein 0 <= i < n so dass a[i] == x false: sonst Alternative: Gib (ersten) Index i zurück. Wir nehmen nichts weiter an als dass wir Gleichheit für t bestimmen können.
180 Einfache Suchalgorithmen Dimensionen der Variationen: Effizienz (Laufzeit-Komplexität) Annahmen über Eigenschaften des Feldes Annahmen über Operationen (Gleichheitstest, etc.)
181 Lineare Suche (Boolesche Rückgabe) Iteriere über alle Elemente und gib true zurück falls ein Element gleich x ist; sonst gib false zurück. boolean linear(int[] a, int x) r = false i = 0 i < a.length &&!r r = a[i] == x i = i + 1 return r
Lineare Suche (Index-Rückgabe) public static int linear(int[] a, int x) { for (int i=0; i<a.length; i++) if (a[i] == x) return i; } return -1; Beachte: eine For-Each- Schleife wäre hier nicht (sinnvoll) anwendbar, da wir i zurückgeben wollen! (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau Siehe package algorithm.search 182
183 Binäre Suche Basierend auf der Annahme, dass das Eingabefeld (etwa aufsteigend) sortiert ist, beginnend in der Mitte des Feldes, suche das Element mittels Halbierung des Suchraums in jedem Schritt. Die Suche beginnt mit i = Mitte.... Wenn a[i] = x, dann gefunden. Wenn a[i] < x, dann in rechter Hälfte fortsetzen. Wenn a[i] > x, dann in linker Hälfte fortsetzen.
Binäre Suche public static int binary(int[] a, int x) { int first = 0; // first index in range int last = a.length - 1; // last index in range while (first <= last) { int middle = first + ((last - first) / 2); if (a[middle] < x) { first = middle + 1; // go to the right } else if (a[middle] > x) { last = middle - 1; // go to the left } else return middle; } return -1; // not found } (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau Siehe package algorithm.search 184
185 Mehrdimensionale Felder Ein 1D-Feld hat einen skalaren Typ als Elementtyp. Ein 2D+-Feld hat einen Feldtyp als Elementtyp. Anwendungsbereiche für mehrdimensionale Felder: Matrizenrechnung Bitmaps im Videospeicher... Mehrdimensionale Felder sind konzeptionell syntaktischer Zucker; allerdings ermöglichen sie auch aggressive Optimierungen.
Beispiel: Matrizenaddition public static int[][] add(int[][] a, int[][] b) { } if (a.length!= b.length a[0].length!= b[0].length) return null; int[][] c = new int[a.length][a[0].length]; for (int i=0; i<a.length; i++) for (int j=0; j < a[0].length; j++) return c; c[i][j] = a[i][j] + b[i][j]; Verschachtelte Schleife für 2D- Addition Laufzeitüberprüfung der Matrizengrößen Laufzeitsallokation der Resultatsmatrix (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau Siehe package data.matrix 186
187 Testrahmen für Matrizenaddition public static void main(string[] args) { int[][] m1 = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; int[][] m2 = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; } print(m1); print(m2); print(add(m1,m2));
Zusammenfassung Anwendungsbereiche für Felder: Tabellenkalkulation Mathematische Problemmodellierung Massendatenverarbeitung (Suchen) Programmatischer Zugriff auf Speicher Ausblick Nächstes Mal: Rekursive Funktionen Übernächstes Mal: Einfache Sortieralgorithmen