[an error occurred while processing this directive]
Rheinland-Pfalz;
Informatik
2008; letzte Aktualisierung: 19.6.2014; Claus Schmitt
![]() |
Startseite Informatik-Rheinland-Pfalz |
Einführung von (statischen) Methoden
Suche des Maximums in einem gegebenen Feld
Methoden auch für Ein- und Ausgabe
Sortieren eines Feldes;
Fehlertolernz
Mischen
zweier sortierter Felder
Feld
halbieren, sortieren und mischen
Sortieren
durch Mischen (Mergesort)
Fachbegiffe
suchen für alle Java-Seiten (Index)
Alle
Java-Quelltexte
Um 10 v. Chr. ordnete Marcus Verrius Flaccus als Erster
ein lateinisches Wörterbuch alphabetisch an. Einführung von (statischen) Methoden Oft gibt es in einem Computerprogramm Abläufe von
Operationen, die mehrfach aufgerufen werden; das Sortieren ist dafür ein
wichtiges Beispiel. Da man solche Handlungsanweisungen nicht immer wieder editieren möchte, modularisiert und
verallgemeinert man diese Befehlsfolgen und nennt dies in Java eine Methode (in
Pascal eine Funktion oder Prozedur). Insbesondere erreicht man durch den Aufruf
von Modulen eine größere Übersichtlichkeit in der Aufrufebene. Suche des
Maximums in einem gegebenen Feld public class Max { static int maximum(int[] a) { int n = a.length; int max = a[0]; for (int i = 1;i < n;i++) if (a[i] > max) max = a[i]; return max; } public static void main(String[] args) { int[] f = new int[] {9, 37,51,2,8,73,3,103,13,5,21}; int max = maximum(f); System.out.printf("Das Maximum ist %d%n",max); } } Ausgabe: Das Maximum ist 103 In diesem Beispiel haben wir die Belegung des Feldes f
gleich bei der Objekterzeugung von f als sog. Arrayliteral angegeben;
interessanter ist es natürlich, das Feld zur Laufzeit z.B. durch einen
Zufallsgenerator zu füllen. Außerdem wollen wir das Feld auch ausgeben. |
||||
Methoden
auch für Ein- und Ausgabe
import java.util.Scanner; public class Max1 { static int feld_laenge() {
Scanner s = new Scanner (System.in);
int n;
//Eingabeschleife bis sinnvolle Feldlänge
do {
System.out.println("Welche Feldlänge?");
n = s.nextInt();
}
while (n < 1);
return n;
}
static void feldein(int[] a) { //Feldeingabemodul for (int i = 0; i < a.length; i++) a[i] = (int) Math.floor(Math.random()*10); } static void feldaus (int[] a) { //Feldausgabemodul System.out.printf("Ausgabe des Feldes:%n"); for (int i = 0; i < a.length; i++) System.out.printf("%3d",a[i]); System.out.printf("%n%n"); } static int maximum(int[] a) { // Bestimmung des Maximums int n = a.length; int max = a[n - 1]; for (int i = n - 2;i >= 0;i--) if (a[i] > max) max = a[i]; return max; } // Hauptprogramm public static void main(String[] args) { int[] f = new int[feld_laenge()]; feldein(f); feldaus(f); System.out.printf("Das Maximum ist %d%n",maximum(f)); } } Beispielausgabe: Welche Feldlänge? 8 Ausgabe des Feldes: 3 2 0 5 0 2 6 5 Das Maximum ist 6 Auch hier erhalten die Methoden zur Ein- und Ausgabe
einen Parameter (das Feld); eine Rückgabe ist jeweils nicht nötig, da der
Feldübergabeparameter und die Feldvariable letztlich auf den gleichen
Speicherplatz referenzieren (in den nächsten Kapiteln werden wir
darlegen, dass Gleichsetzen von Objekten immer die Zuweisung des gleichen
Speicherplatzes bedeutet). |
||||
|
||||
Mischen
zweier sortierter Felder
Für das Mischen übertragen wir folgenden Algorithmus:
import java.util.Scanner; public class Mischen { // Hier erhält auch eine Variable den Modifier static; // dadurch steht der Scanner in allen Methoden zur Verfügung static Scanner s = new Scanner (System.in); // Welche Länge soll ein Feld haben? static int feld_laenge(int ug,int og) { // Untere und obere Grenze als Übergabeparameter int n; // Eingabeschleife do { System.out.printf(" Ganze Zahl ab %d bis %d%n",ug,og); if (s.hasNextInt()) n = s.nextInt(); else {s.nextLine(); n = ug - 1;} //Damit Eingabeschleife weiter läuft } while ((n < ug) ||(n > og)) ; return n; }
//Die bereits bekannten Methoden sind wieder klein gedruckt
static void feld_ein(int[] c) {
//Feldeingabemodul
for (int i = 0; i < c.length; i++)
c[i] = (int) Math.floor(Math.random()*10);
}
static void feld_aus(int[] c) { // Feldausgabemodul System.out.println(); for(int i = 0; i <c.length; i++) System.out.printf("%3d,",c[i]); } static void max_sort(int[] c) { //Sortieren mit straight selection int max; int pos; int n = c.length; for (int i = n - 1; i > 0; i--) { max = c[i]; pos = i; for (int j = i - 1 ; j >= 0; j--) if (c[j] > max) { max = c[j]; pos = j; } c[pos] = c[i]; c[i] = max; } } static int [] mischen (int[]a, int[] b ) { //sortierte Felder mischen,indem man jeweils die Feldelemente vergleicht // und das kleinere in einem dritten Feld notiert. // Feldlängen int n = a.length; int m = b.length; // neues Feld erzeugen int[] c = new int[n + m]; int i = 0; int j = 0; int k = 0; // Jeweils prüfen, welches Feldelement in c kommt // Aufhören, wenn ein Feld alle Werte eingefügt hat; // Dann muss man später nur noch mit dem anderen Feld auffüllen while ((k < n + m) && (i != n) && (j != m)) { if (a[i] <= b[j]) { c[k] = a[i]; i++; } else { c[k] = b[j]; j++; } k++; } // Wenn aus a schon alle Werte eingefügt sind, muss man nur noch die Werte // aus b auffüllen; etc. // Die Werte der Laufvariablen k, i und j werden aus der While-Schleife //übernommen. if (i == n ) for (int l = k ; l < (n + m); l++) { c[l] = b[j]; j++;} else for (int l = k ; l < (n + m); l++) { c[l] = a[i]; i++;} return c; }
public static void main (String[] args) {
// Laenge der Felder erfragen
System.out.printf("Wie lange ist das erste Feld? (höchstens 20) %n");
int n = feld_laenge(1,20);
System.out.printf("Wie lange ist das zweite Feld? (höchstens 20) %n");
int m = feld_laenge(1,20);
// 2 Felder einrichten, einlesen und sortieren int[] a = new int[n]; int[] b = new int[m]; feld_ein(a); feld_ein(b); System.out.printf("%nDie beiden unsortierten Felder%n"); feld_aus(a); feld_aus(b); max_sort(a); max_sort(b); System.out.printf("%nDie beiden sortierten Felder%n"); feld_aus(a); feld_aus(b); int[] c = new int[n+m]; // Zwei sortierte Felder mischen c = mischen(a,b); System.out.printf("%nDas sortierte Feld nach dem Mischen%n"); feld_aus(c); } } Wie lange ist
das erste Feld? (höchstens 20) Feld
halbieren, sortieren und mischen import java.util.Scanner; public class Halb_Sort { static Scanner s = new Scanner (System.in); // Zähler für Vergleiche static int v= 0; static void feld_ein(int[] c) {
//Feldeingabemodul
for (int i = 0; i < c.length; i++)
c[i] = (int) Math.floor(Math.random()*10);
}
static int feld_laenge(int ug) {
// Untere Grenze als Übergabeparameter
int n;
do {
System.out.printf(" Ganze Zahl ab %d %n",ug);
if (s.hasNextInt())
n = s.nextInt();
else {s.nextLine();n = ug - 1;}
}
while (n < ug);
return n;
}
static void max_sort(int[] c) { //Sortieren mit straight selection int max; int pos; int n = c.length; for (int i = n - 1; i > 0; i--) { max = c[i]; pos = i; for (int j = i - 1 ; j >= 0; j--) { v++; if (c[j] > max) { max = c[j]; pos = j; } } c[pos] = c[i]; c[i] = max; } } static int [] mischen (int[]a, int[] b ) { //Wie oben; bis auf den Zähler v int n = a.length; int m = b.length; int[] c = new int[n + m]; int i = 0; int j = 0; int k = 0; while ((k < n + m) && (i != n) && (j != m)) { if (a[i] <= b[j]) { c[k] = a[i]; i++; } else { c[k] = b[j]; j++; } k++; v++; } if (i == n ) for (int l = k ; l < (n + m); l++) { c[l] = b[j]; j++;} else for (int l = k ; l < (n + m); l++) { c[l] = a[i]; i++;} return c; } static int[] sort (int[] a) { int n = a.length; if (n > 1) { // Zwei neue Felder anlegen int m = n / 2; int []l =new int[m]; int []r =new int[n-m]; // Die zwei Hälften mit den passenden Feldelementen füllen for (int i = 0; i < m; i++) l[i] = a[i]; for (int i = 0; i < (n-m); i++) r[i] = a[m +i];
// jede Hälfte sortieren
max_sort(l);
max_sort(r);
// Die beiden sortierten Hälften zusammenfügen
a = mischen(l,r);
}
return a;
}
public static void main(String[] args) { System.out.printf("Wie lange soll das Feld sein? %n"); int n = feld_laenge(1); // Feld einrichten und einlesen int[] f = new int[n]; feld_ein(f); // Sortieren f = sort(f); System.out.printf("%d Vergleiche", v); } } Beispielausgabe:
Wie lange soll das Feld sein?
Falls man sich die Mühe macht und das Feld sogar in
vier Teile teilt, sortiert und mischt, schwankt die Zahl der
Vergleiche sogar nur noch um 1380
(vgl. Quelltext Viertel_Sort.java). |
||||
Sortieren
durch Mischen (Mergesort) Wenn wir im folgenden Beispiel von n =
8 Feldelementen ausgehen, erreichen wir mit drei
Halbierungsdurchgängen jeweils als Feldlänge 1.
Entsprechend vollzieht sich auch das Mischen in drei Ebenen:
Insgesamt gibt es also 3 * 4 = log( 8) * 8 / 2 Vergleiche; damit ist die bekannte Beziehung für den Aufwand n * log (n) motiviert. Um Mergesort zu realisieren, müssen
wir im letzten Programm (Halb_Sort) nur die Methode sort
durch folgenden rekursiven Ansatz
austauschen; alle anderen Methoden - auch das Mischen - sind bereits
entwickelt! Die Methode max_sort (Straight Selection) entfällt
naturgemäß ganz! static int[] sort (int[] a) { // Rekursionsende bei Feldlänge 1 int n = a.length; if (n > 1) { // Zwei neue Felder anlegen int m = n / 2; int []l =new int[m]; int []r =new int[n-m]; // Die zwei Hälften mit den passenden Feldelementen füllen
for (int i = 0; i < m; i++)
l[i] = a[i];
for (int i = 0; i < (n-m); i++)
r[i] = a[m +i];
// jede Hälfte sortieren; rekursiver Aufruf!
l = sort(l);
r = sort(r);
// Die beiden sortierten Hälften zusammenfügen
a = mischen(l,r);
}
return a;
}
Wesentliche Vergleiche werden hier nur
in der Mischenmethode gezählt: Wie lange soll das Feld sein? 530
Vergleiche |
||||
|
||||
Weitere
Literaturempfehlungen finden Sie hier
|
![]() |
Startseite Informatik-Rheinland-Pfalz |