Sie sind auf Seite 1von 27

Arrays

Arrays (Felder): spezielle Objekte zum Speichern gleichartiger Elemente.


Array-Variablen (Namen der Objekte)
int [] a; // (int a[]; auch erlaubt)
byte[][] b; // (byte b[][]; auch erlaubt)

Array-Erzeugung
1) Explizit mittels new
Syntax: new Typ[int-Ausdruck]
a = new int[5];

2) Liste von Initialisierern (nur bei der Variablendefinition möglich)


int [] a = { 1, 2, 3};

3) Kombination
a = new int[] { 1, 2, 3}; // Längenangabe nicht erlaubt!!

Tran / Hettel GDI 2 1


Arrays

Array als Objekt


int[] a = new int[4];
out.println(a.getClass()); // Ausgabe class [I
// [ für Array I für int
out.println(a);

a.toString() wurde aufgerufen. Standard-Implementierung ist die Ausgabe des


Klassennamen und des Hashcodes.
Der Name darf später auf ein anderes Objekt verweisen:
a = new int[100];
...
a = null; // a zeigt auf kein Objekt

Tran / Hettel GDI 2 3


Arrays

Zugriff auf Array-Elemente über den Index:


int [] a = new int[10];
a[0] = 2;
a[3] = a[0] + 3;

- Index fängt von 0 an.


- Maximaler Index von Array a ist a.length – 1.
- Zugriff außerhalb 0 .. length-1 führt zu einer Ausnahme (Exception).

final int MAX_SIZE = 4;


int intArray[] = new int[MAX_SIZE];
// fehlerhafte Schleife - eins zu viel
for (int i = 0; i <= MAX_SIZE; i++)
{
intArray[i] = i;
}

Tran / Hettel GDI 2 4


Arrays

Initialisierung von Arrays


int[] a = new int[4];
for (int elem : a) // Array ausgeben
out.println(elem); // 0

- Initialisierung direkt bei der Erzeugung.


int[] a= {1, 2*2, 3*3, 4*4};
// auch möglich
// int[] a = new int[] {1, 2*2, 3*3, 4*4};

- Das Array elementweise initialisieren.


int[] a = new int[4];
for (int i = 0; i < a.length; ++i)
a[i] = (i+1)*(i+1);

- Das Array mit Hilfe von java.util.Arrays mit dem gleichen Wert füllen.
int[] a = new int[4];
java.util.Arrays.fill(a, 5);

Tran / Hettel GDI 2 5


Arrays

Kopieren von eindimensionalen Arrays


Versuch: int [] a = ...;
Zuweisung ....
int [] b = a;
// Falsch!!! a und b zeigen auf dasselbe Objekt.
// Keine Kopie wurde erstellt.

1. Möglichkeit:
Ein neues Array erzeugen und das Array elementweise kopieren:
int [] b = new int[a.length]; // neues Array erzeugen
for (int i = 0; i < a.length; ++i)
{
b[i] = a[i]; // Element kopieren
}

Tran / Hettel GDI 2 6


Arrays

2. Möglichkeit:
Ein neues Array erzeugen und das ganze Array mit Hilfe der Klassenmethode
System.arraycopy kopieren.
int [] b = new int[a.length]; // neues Array erzeugen
System.arraycopy(a, 0, b, 0, a.length);

Syntax von arraycopy:


System.arraycopy(Object vonArray, int abIndex,
Object nachArray, int abZielIndex,
int anzahl);

int [] c = new int[2*a.length];


System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(a, 0, c, a.length, a.length);
// c enthält 2 Kopien von a

Tran / Hettel GDI 2 7


Arrays

3. Möglichkeit: Verwendung der Methode clone.


int[] a = {1,2,3};
int [] b = (int [])a.clone(); // clone-Methode liefert ein
// Objekt vom Typ Object. Daher muss man das Ergebnis
// casten (vor 1.5)
// Ab Java 1.5 kann man schreiben int[] b = a.clone();

4. Möglichkeit: Verwendung der Methode java.util.Arrays.copyOf.


double [] copy = java.util.Arrays.copyOf(a, a.length);

Um Bereiche zu kopieren: java.util.Arrays.copyRange.

Tran / Hettel GDI 2 8


Arrays

Array einlesen
Elemente eines Arrays müssen einzeln eingelesen werden.
int [] a = new int[10];
for (int i = 0; i < a.length; ++i){
a[i] = ReadUtil.nextInt("a[" + i + "] = ");
}

Array ausgeben
for (int i = 0; i < a.length; ++i) {
out.print( "a[" + i + "] = " + a[i] + "\t");
}

double[] a = {1.0, 2.2, 3.1};


for (double elem : a){
out.print( elem + "\t");
oder }
out.println();

out.println(java.util.Arrays.toString(a));
oder
Tran / Hettel GDI 2 9
Arrays

Array von Objekten(namen)


String[] b = new String[3];

Variable b vom Typ String[]


b.length vom Typ int
b[0], b[1], b[2] Variablen vom Typ String (d.h. Etikette /Referenzen für String-
Objekte)

length
b 3
b[0] b[1] b[2]

Tran / Hettel GDI 2 10


Arrays

b[0] = "OK";
b[1] = new String("Test");

b 3
b[0] b[1] b[2]

"OK" "Test"

Tran / Hettel GDI 2 11


Arrays

Erzeugung und Initialisierung


String[] c = {"alles", "ist", "fein"};
Button[] bArray = { new Button("0"), new Button("1") };

Beachte
String[] b = new String[3];
b[0] = "OK";
b[1] = "test";
b = new String[5]; // Objekte "OK" und "test" gehen verloren

Tran / Hettel GDI 2 12


Arrays

Spezialfall: Array von Arrays


Arrays sind auch Objekte, daher möglich:
int[][] a = new int[3][2];

a[0][0]
3
a 2
a[0] a[0][1]

a[1] 2

a[2]
2

a vom Typ int[][] (Array von Array von int),


a[0], a[1], a[2] vom Typ int[] (Array von int),

a[0][0], a[0][1], ... a[2][1] sind vom Typ int.

Tran / Hettel GDI 2 13


Arrays

int [][] d = { {1}, {1, 2}, {1, 2, 3}};

3
d 1
d[0]
1
d[1] 2
1 2
d[2]
3
1 2 3
Entsprechend:
int[][][] x = new int[3][4][];
char[][][][] c = new char[3000][][][];

Tran / Hettel GDI 2 14


Arrays

Beispiel

double [][] d;
d = new double[3][];
for (int i = 0; i < d.length; ++i)
{
d[i] = new double[i+1];
for (int j = 0; j < d[i].length; ++j)
{
d[i][j]= ReadUtil.nextDouble("d[" + i+ "]["+ j + "] = ");
}
}

Tran / Hettel GDI 2 15


Arrays

String und Array von char


String str = "abcdef";
char[] c = str.toCharArray();
// c enthält die Zeichen 'a', 'b', .. , 'f'
String neu = new String(c);
// String-Objekt aus einem Array von char erzeugen
out.println(c); // ist OK Es gibt eine Methode, um Array von
// char auszugeben
out.println("Array enthält " + c); // NOK!!

Typumwandlung
double[] x = {1, 2};
int[] y = { 1, 2};
x=y;
// Fehler !! ein int[] kann nicht double[] umgewandelt werden
x = (double []) y; // Auch Fehler

Tran / Hettel GDI 2 16


Arrays

Array von Objekten kopieren bzw. klonen


Man muss die Objekte ggf. kopieren bzw. klonen.
Beispiel

double[][] x = { {1,2} , {3, 4} };


double[][] y = new double[x.length][];
for (int i = 0; i < x.length; ++i)
{
y[i] = new double[x[i].length];
for (int j = 0; j < y[i].length; ++j)
{
y[i][j] = x[i][j];
}
}

Tran / Hettel GDI 2 17


Arrays

Andere Möglichkeit (geht nicht für alle Objekte)


double[][] y = (double[][]) x.clone();
for (int i = 0; i < x.length; ++i)
{
y[i] = (double[]) (x[i].clone());
}

Klasse java.util.Arrays (Ihr Freund bei der Arbeit mit Arrays)


+ static void sort(array) // zum Sortieren
+ static int binarySearch(array, elem) // Index wird zurückgegeben, falls das Element im
Array ist. Sonst wird ein negativer Wert zurückgegeben
+ static void fill(array, wert) // zum Füllen
+ static boolean equals(array1, array2) // zum Vergleichen
+ static String toString(array) // Ausgabe als String (für Array von elementaren
Datentypen)
+ static String deepToString(objArray) // Ausgabe als String (für Array von Objekten)

Tran / Hettel GDI 2 18


Objekte als Parameter

Array als Parameter einer Methode


public static long squareSum(int[] a)
{
long ret = 0;
for (int elem: a)
{
ret += elem*elem;
}
return ret;
} // end of squareSum

kopieren
squareSum

Tran / Hettel GDI 2 19


Objekt als Parameter

In Java kann man die übergebenen Objekte nicht schützen.


public static void f(final int[] a) // a wird geschützt
{
...
a = new int[3]; // Fehler, a ist final!!
...
a[0] = 123; // Erlaubt
...
}

Man muss also ggf. mit einer Kopie oder mit einem Vermittler arbeiten.

Tran / Hettel GDI 2 20


Objekte als Methodenrückgabe

z.B. Array als Rückgabe einer Methode

public static double[] create(int n) {


double[] result = new double[n];
for (int i = 0; i < n; ++i) {
result[i] = Math.sin(Math.toRadians(i));
}
return result;
}

kopieren kopieren (Verraten, wo das Objekt liegt)


5 5 create

Array auf dem Heap


erzeugt durch new

Tran / Hettel GDI 2 21


Fallstudie – Tiefensuche mit Backtracking

Backtracking (Auszug aus wikipedia.de)


Backtracking geht nach dem Versuch-und-Irrtum-Prinzip (trial and error) vor, das
heißt, es wird versucht, eine erreichte Teillösung zu einer Gesamtlösung
auszubauen. Wenn absehbar ist, dass eine Teillösung nicht zu einer
endgültigen Lösung führen kann, wird der letzte Schritt beziehungsweise
werden die letzten Schritte zurückgenommen, und es werden stattdessen
alternative Wege probiert. Auf diese Weise ist sichergestellt, dass alle in Frage
kommenden Lösungswege ausprobiert werden können (Prinzip
des Ariadnefadens). Mit Backtracking-Algorithmen wird eine vorhandene
Lösung entweder gefunden (unter Umständen nach sehr langer Laufzeit), oder
es kann definitiv ausgesagt werden, dass keine Lösung existiert. Backtracking
wird meistens am einfachsten rekursiv implementiert und ist ein prototypischer
Anwendungsfall von Rekursion.

Tran / Hettel GDI 2 22


Fallstudie – Tiefensuche mit Backtracking

Beispiel Sudoku
public static boolean sudoku(int[][] m, int zeile, int spalte)
{
// suche nach einem freien Feld
while (m[zeile][spalte] != 0)
{
spalte++;
if (spalte == m.length)
{
spalte = 0;
zeile++;
// haben wir alle Felder belegt? Trivialer Fall
if (zeile == m.length)
{
// wir sind fertig und haben einen Lösung gefunden
return true;
}
}
}

Tran / Hettel GDI 2 23


Fallstudie – Tiefensuche mit Backtracking

Beispiel Sudoku

// an dieser Stelle haben wir ein leeres Feld gefunden


for (var i = 1; i <= m.length; i++)
{
if (test(m, zeile, spalte, i) == true)
{
// Probieren mit der Zahl i
m[zeile][spalte] = i;
// das Problem wird dadurch um ein Elem. kleiner
// Backtracking probiere mit aktueller Zahl
if (sudoku(m, zeile, spalte) == true)
{
return true;
}
}
}
m[zeile][spalte] = 0;
return false;
}

Tran / Hettel GDI 2 24


Fallstudie – Dynamische Programmierung

Dynamische Programmierung (Auszug aus wikipedia.de)


Dynamische Programmierung ist eine Methode zum algorithmischen Lösen eines
Optimierungsproblems durch Aufteilung in Teilprobleme und systematische
Speicherung von Zwischenresultaten.

Dynamische Programmierung kann erfolgreich eingesetzt werden, wenn
ein Optimierungsproblem aus vielen gleichartigen Teilproblemen besteht und eine
optimale Lösung des Problems sich aus optimalen Lösungen der Teilprobleme
zusammensetzt. Dies nennt man Optimalitätsprinzip von Bellman. In der dynamischen
Programmierung werden zuerst die optimalen Lösungen der kleinsten Teilprobleme
direkt berechnet und dann geeignet zu einer Lösung eines nächstgrößeren Teilproblems
zusammengesetzt. Dieses Verfahren setzt man fort, bis das ursprüngliche Problem
gelöst wurde. Einmal berechnete Teilergebnisse werden in einer Tabelle gespeichert.
Bei nachfolgenden Berechnungen gleichartiger Teilprobleme wird auf diese
Zwischenlösungen zurückgegriffen, anstatt sie jedes Mal neu zu berechnen, was zu
einer Senkung der Laufzeit führt. Wird die dynamische Programmierung konsequent
eingesetzt, vermeidet sie kostspielige Rekursionen, weil bekannte Teilergebnisse
wiederverwendet werden.

Tran / Hettel GDI 2 25


Fallstudie – Dynamische Programmierung

Beispiel Needleman-Wunsch-Algorithmus (1970)


Gegeben seien zwei Protein-Sequenzen.
Gesucht: Ähnlichkeitsfaktor in Abhängigkeit von einer geg. Funktion.
Hier werden zwei String verglichen. Gegeben seien zwei Zeichenketten

Man verwendet eine -Matrix 𝐸 , um die Ähnlichkeitswerte von


und abzuspeichern.
Als Startwert setzt man
1) E[0][0] = 0 // leere Zeichenketten sind nicht ähnlich
2) E[i][0] = 0 // ist nicht ähnlich mit einer leeren Zeichenkette,

3) E[0][j] = 0 // leere Zeichenkette ist nicht ähnlich mit

Tran / Hettel GDI 2 26


Fallstudie – Dynamische Programmierung

Beispiel Needleman-Wunsch-Algorithmus (1970)


E[i][j] ist dann

wobei zum Beispiel bonus(a, b) = 1 falls a = b ist.


Der Ähnlichkeitsfaktor ist dann der Wert E[n][m]

Weitere Dynamische Programmierungsprobleme siehe:


https://medium.com/@codingfreak/top-50-dynamic-programming-practice-
problems-4208fed71aa3

Tran / Hettel GDI 2 27


Fallstudie – Dynamische Programmierung

public static int berechne(String x, String y) {


int n = x.length();
int m = y.length();
// Matrix für die Zwischenwerte erzeugen
int[][] E = new int[n + 1][m + 1];
// 1) 2) 3) gelten automatisch
// Berechne zeilenweise die Ähnlichkeitswerte
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int bonus = 0;
// Zeichenposition fängt bei 0 an daher hier i-1 statt i
if (x.charAt(i - 1) == y.charAt(j - 1)) {
bonus = 1;
}
// Bestimme den besten Ähnlichkeitswert
E[i][j] = Math.max(E[i - 1][j],
Math.max(E[i][j - 1], E[i - 1][j - 1] + bonus));
}
}
// Das Ergebnis ist das letzte Element
return E[n][m];
}

Tran / Hettel GDI 2 28