Ludwig-Maximilians-Universität München München, 04.12.2009 Institut für Informatik Prof. Dr. Christian Böhm Annahita Oswald, Bianca Wackersreuther Einführung in die Programmierung WS 2009/10 Übungsblatt 7: Imperative Programmierung, Parameterübergabe Besprechung: 14./16./17./18.12.2009 Ende der Abgabefrist: Montag, 14.12.2009 10:00 Uhr. Hinweise zur Abgabe: Geben Sie bitte Ihre gesammelten Lösungen zu diesem Übungsblatt in einer Datei loesung07.zip unter http://www.pst.ifi.lmu.de/uniworx/ ab. Bitte beachten Sie, dass die Aufgabe 7-2 nicht in die Bonusregelung eingeht. Bereiten Sie diese aber bitte trotzdem vor, damit Sie der Übung optimal folgen können. Aufgabe 7-1 Sieb des Eratosthenes 10 Punkte Nach Eratosthenes, einem Mathematiker des alten Griechenlands, wird folgender Algorithmus zur Bestimmung aller Primzahlen bis zu einer bestimmten Zahl,,Sieb des Eratosthenes genannt: Angenommen, Sie wollen alle Primzahlen 1000 bestimmen. Erstellen Sie ein Array vom Typ boolean[] der Länge 1001. Die Elemente mit Index 0 und 1 sollen den Wert false haben, alle anderen zunächst den Wert true. (0 und 1 sind per definitionem keine Primzahlen.) Fangen Sie nun an, das Array von vorne an nach Elementen vom Wert true zu durchsuchen. Für jedes solche Element a an Index i a setzen Sie den Wert aller Elemente b, deren Index i b ein ganzzahliges Vielfaches von i a ist, auf den Wert false. Wenn Sie die Suche beendet haben, sind die Indizes mit Wert true die Primzahlen 1000. (a) Schreiben Sie in einer Klasse Primzahlen eine Methode public static boolean[] siebdeseratosthenes(int n), die für eine natürliche Zahl n > 0 die oben beschriebene Methode implementiert. (b) Ergänzen Sie die Klasse um eine Methode public static void printprimzahlen(int n), die für eine natürliche Zahl n > 0 die Primzahlen n auf die Konsole ausgibt. (c) Ergänzen Sie die Klasse um eine main-methode, die die Methode printprimzahlen mit einem int- Wert als Parameter aufruft. Geben Sie Ihre Lösung in einer Datei Primzahlen.java ab. 1
Lösungsvorschlag: public class Primzahlen { Implementiert den Algorithmus "Sieb des Eratosthenes". Das resultierende boolesche Array der Länge <code>n+1</code> enthält den Wert <code>true</code> genau an den Stellen, deren Indizes Primzahlen sind. @param n Maximum der gesuchten Primzahlen @return Array der Länge <code>n+1</code> mit dem Wert <code>true</code> an genau den Feldern, deren Index eine Primzahl ist public static boolean[] siebdeseratosthenes(int n) { boolean[] primzahlen = new boolean[n + 1]; for (int i = 2; i < primzahlen.length; i++) { primzahlen[i] = true; for (int i = 0; i < primzahlen.length; i++) { if (primzahlen[i]) { int m = 2; while (i m < primzahlen.length) { primzahlen[i m] = false; m++; return primzahlen; Gibt die Primzahlen <code>n</code> aus. @param n Maximum der gesuchten Primzahlen public static void printprimzahlen(int n) { boolean[] primzahlen = siebdeseratosthenes(n); System.out.println("Die Primzahlen <= " + n + " sind:"); for (int i = 0; i < primzahlen.length; i++) { if (primzahlen[i]) { System.out.println(i); Ruft die Methode printprimzahlen auf, der eine Zahl n als integer übergeben wird. int n = 10; printprimzahlen(n); 2
Aufgabe 7-2 Türme von Hanoi 0 Punkte Ein bekanntes Spiel trägt den Namen,,Türme von Hanoi. Das Spiel wird mit n Scheiben verschiedener Größe gespielt, die auf Stäbe A, B, C gesteckt werden können. Zu Beginn stecken alle n Scheiben auf Stab A und zwar derart, dass jeweils eine kleinere Scheibe auf einer größeren Scheibe liegt (siehe Abbildung). Die Aufgabe besteht darin, die Scheiben von Stab A nach Stab C umzustecken; Stab B kann dabei als Zwischenspeicher verwendet werden. Es sind dabei folgende zwei Regeln zu beachten: In jedem Schritt darf nur genau eine Scheibe bewegt werden. Eine größere Scheibe darf nie auf einer kleineren Scheibe liegen. A B C (a) Schreiben Sie in einer Klasse Hanoi eine Methode public static stecke(int n, char A, char B, char C), die für eine natürliche Zahl n > 0 und drei Character A, B und C die oben beschriebene Methode implementiert. Die einzelnen Züge sollen dabei auf die Konsole ausgegeben werden. (b) Ergänzen Sie die Klasse um eine main-methode, um Ihre Methode mit geeigneten Werten zu testen. Lösungsvorschlag: Die Klasse Hanoi implementiert die Türme von Hanoi public class Hanoi { Bewegt n Scheiben von Stab A nach Stab C und benutzt als Zwischenspeicher Stab B. private static void stecke(char A, char B, char C, int n) { if (n == 1) System.out.println("Stecke die oberste Scheibe von " + "Stab " + A + " auf Stab " + C + "."); else { stecke(a, C, B, n - 1); stecke(a, B, C, 1); stecke(b, A, C, n - 1); Bewegt für n Scheiben von einem Stab A nach C über B. @param args, die Kommandozeilenparameter stecke( A, B, C, 3); 3
Aufgabe 7-3 Parameterübergabe 10 Punkte Gegeben sei die Java-Klasse Parameteruebergabe. public class Parameteruebergabe { static String a = "A"; static String b = "B"; static String[] ab = { a, b ; public static void swap(string s0, String s1) { String temp = s0; s0 = s1; s1 = temp; public static void swap(string[] s) { String temp = s[0]; s[0] = s[1]; s[1] = temp; public static void proverb() { System.out.println("Wer " + a + " sagt, muss auch " + b + " sagen!"); System.out.println("Also muss auch " + ab[0] + " sagen, wer " + ab[1] + " sagt?"); swap(a, b); swap(ab); Welche Ausgabe erzeugt das Programm? Begründen Sie Ihre Antwort ausführlich. Geben Sie Ihre Lösung in einer Datei Parameteruebergabe.txt ab. 4
Lösungsvorschlag: Ausgabe: Also muss auch A sagen, wer B sagt? Also muss auch A sagen, wer B sagt? Also muss auch B sagen, wer A sagt? Diese Ausgabe lässt sich am besten anhand der Stack- und Heap-Struktur erklären. Die ersten beiden Zeilen kommen durch folgende Situation zustande: <adr3> : {<adr1>, <adr2> Bei dem Aufruf swap(a, b) werden die Parameter by value übergen. Also für a wird der Wert adr1 übergeben, für b der Wert adr2. Damit ergibt sich folgende Situation, die zu Zeile 3 und 4 der Ausgabe # 1 führt. (Wert-ändernde Zuweisungen sind rot markiert.) temp = <adr1> s1 = <adr2> <adr1> s0 = <adr1> <adr2> <adr3> : {<adr1>, <adr2> Bei dem Aufruf swap(ab) wird der Parameter ebenfalls by value übergen. Also für ab wird der Wert adr3 übergeben. Im folgenden wird direkt auf dem dadurch referenzierten Array gearbeitet, wodurch sich schliesslich # 2 Zeile 5 und 6 der Ausgabe ergeben.(änderungen auf dem Heap sind rot markiert.) temp = <adr1> s = <adr3> <adr3> : {<adr1><adr2>,<adr2><adr1> # 3 5