Algorithmik II 1. ¨Ubung Organisatorisches: Die Termine der

Werbung
Algorithmik II
1. Übung
Organisatorisches:
Die Termine der Übungen, die Übungsblätter und weitere Informationen sind auf der Webseite der
Übungen zu finden:
http://www8.informatik.uni-erlangen.de/IMMD8/Lectures/SS03/algo2/uebungen.html
Jeder Studierende muß sich zu einer Tafel- und einer Rechnerübung anmelden. Die Anmeldungen
zu den Übungen ist verbindlich! Die Anmeldung zu den Übungen erfolgt ¨uber das Web-AnmeldeSystem “WAS”
http://www.was.dienste.uni-erlangen.de
Der Übungsbetrieb beginnt am Montag den 14. April 2003.
Aufgabe 1
a) Erklären Sie die Unterschiede zwischen anweisungs-, funktions-, regel- und objektorientierter
Programmierung.
Lösungsvorschlag:
14. – 25. April 2003
-1-
Sommersemester 2003
Algorithmik II
1. Übung
anweisungsorientierte Programmierung
zentrale
Sprachelemente
Variablen
und
Anweisungen,
die den Zustand
der
Variablen
ändern
Programm
Sequenz von Anweisungen
Programmausführung
14. – 25. April 2003
funktionsorientierte
Programmierung
Funktionen und
ihre Anwendung
auf Parameter
Ansammlung
nebeneinander
stehender Funktionsdefinitionen
Ausführung der Auswertung der
Anweisungen
Programmfunk”
in der notierten tion“,
wobei
Reihenfolge.
hierzu evtl. noch
Beim Erreichen viele
weitere
einer Sprungan- Funktionen ausweisung
wird gewertet werden
abhängig
von müssen.
aktuellen
Variablenwerten
entschieden,
welche Anweisung als nächste
ausgeführt wird.
-2-
regelorientierte
Programmierung
objektorientierte
Programmierung
Logische Folgerung
Objekte,
die
einen
inneren
Zustand
und
Methoden haben,
mit denen dieser
Zustand geändert
werden
kann.
Jedes Objekt hat
einen bestimmten
Typ.
Ansammlung von Ansammlung von
Fakten und Re- Objekten
geln
Ableitung neuer
Aussagen
aus
bereits bekannten;
Versuch,
eine Anfrage zu
verifizieren
Objekte schicken
einander Nachrichten, indem sie
die Methoden der
anderen Objekte
ansprechen
Sommersemester 2003
Algorithmik II
1. Übung
b) Welche dieser Konzepte finden sich in den Programmiersprachen Scheme und Java?
Lösungsvorschlag:
Scheme:
• Funktionsorientierte Programmierung:
In Scheme ist alles eine Funktion. Es stehen mehrere Funktionsdefinitionen nebeneinander. Ein Programm wird gestartet, indem eine Funktion ausgeführt wird.
• Anweisungsorientierte Programmierung:
Zustandsänderungen von Variablen durch den set!-Befehl, z.B. (set! summe (+
summe wert)), oder append!
Java:
• Anweisungsorientierte Programmierung:
Ausführung von Anweisungen in der notierten Reihenfolge, Sprunganweisungen
(do/while)
• Objektorientierte Programmierung:
Objekte können andere Objekte ansprechen durch Aufruf der Methoden der anderen
Objekte
Auch in Scheme lassen sich objektorientierte Konzepte realisieren. Sie sind jedoch nicht Teil
des Sprachumfangs.
Aufgabe 2
Schreiben Sie ein Java-Programm zur Berechnung der Fakultätsfunktion. Schreiben Sie sowohl eine
rekursive als auch eine iterative Methode.
Lösungsvorschlag:
• Rekursive Fassung:
int fakRek(int n) {
if (n <= 1) {
return 1;
}
else return n * fakRek(n-1);
}
• Iterative Fassung mit abweisender Schleife:
int fakIter(int n) {
int i = 1;
int ergebnis = 1;
while (i <= n) {
ergebnis *= i;
i++;
}
return ergebnis;
}
14. – 25. April 2003
-3-
Sommersemester 2003
Algorithmik II
1. Übung
• Iterative Fassung mit nichtabweisender Schleife:
int fakIter2(int n) {
int i = 1;
int ergebnis = 1;
do {
ergebnis *= i;
i++;
} while (i <= n);
return ergebnis;
}
Je nach Wissensstand der Übungsteilnehmer kann hier auch darauf eingegangen werden, daß in Scheme (Abelson/Sussman, Kapitel 1.21) zwischen rekursiven Prozeduren
und rekursiven Prozessen unterschieden wurde. Ein iteratives Programm“ in Scheme
”
ist ein rekursives Programm, das einen iterativen Prozeß erzeugt.
In Java dagegen werden iterative Prozesse durch nicht-rekursive Methoden erzeugt, indem Schleifen verwendet werden.
Im Gegensatz zu Scheme gilt für Java, daß eine Java-Methode noch kein vollständiges,
lauffähiges Java-Programm ist. Um ein solches zu erhalten, ist mindestens folgendes
notwendig:
• Die Methode muß in eine Klasse eingebettet werden.
• Man braucht weiterhin eine Klasse mit einer Methode main. Die Ausführung
eines Java-Programms beginnt immer mit der Methode main der als public
deklarierten Klasse. Jedes Java-Programm muß eine solche Klasse enthalten. In
der main-Methode werden Objekte dieser oder auch anderer Klassen erzeugt und
deren Methoden aufgerufen. Die Klassendefinitionen müssen entweder im Programm vorhanden sein oder aus Bibliotheken übernommen werden.
Ein vollständiges Programm um die obigen Methoden herum könnte z.B. so aussehen:
public class Fakultaet {
int fakIter(int n) {
...
}
int fakRek(int n) {
...
}
public static void main(String[] args) {
int n = 5;
Fakultaet f = new Fakultaet();
System.out.print("Rekursiv: " + n + "! ist ");
System.out.println(f.fakRek(n) + ".");
System.out.print("Iterativ: " + n + "! ist ");
14. – 25. April 2003
-4-
Sommersemester 2003
Algorithmik II
1. Übung
System.out.println(f.fakIter(n) + ".");
}
}
Aufgabe 3
Ablaufstrukturen
Realisieren Sie die nachfolgend angegebene Funktion sowohl als Struktogramm als auch in Java.



a2 + (a + 1)2 + . . . + (b − 1)2 + b2
f (a, b) = a2

 2
b + (b + 1)2 + . . . + (a − 1)2 + a2
falls a < b
falls a = b
falls b < a
Lösungsvorschlag:
Mit Hilfe von Struktogrammen kann man einen Algorithmus zunächst einmal unabhängig von der Syntax einer bestimmten Programmiersprache formulieren.
int sum_quad (int a, int b)
summe = 0
solange a kleiner oder gleich b
Erhöhe summe um a*a
Erhöhe a um 1
Gib summe zurück
int f(int a, int b)
Ist a gleich b ?
Nein
Ja
Ist a kleiner als b ?
Gib a*a zurück
Ja
Nein
Gib sum_quad(a,b) zurück
Gib sum_quad(b,a) zurück
int sumQuad(int a, int b) {
int summe = 0;
while (a <= b) {
summe += a * a;
a++;
}
14. – 25. April 2003
-5-
Sommersemester 2003
Algorithmik II
1. Übung
return summe;
}
int f(int a, int b) {
if (a == b)
return a*a;
else if (a < b) return sumQuad(a, b);
else
return sumQuad(b, a);
}
Aufgabe 4
Wertzuweisung
Gegeben sei folgendes Java-Programm:
class UnsereKlasse {
int Komponente;
}
public class KomponentenTester
{
public static void main (String[] args)
{
UnsereKlasse Objekt1 = new UnsereKlasse ();
UnsereKlasse Objekt2 = new UnsereKlasse ();
01
02
03
04
05
06
Objekt1.Komponente
Objekt1.Komponente
Objekt2.Komponente
Objekt2 = Objekt1;
Objekt2.Komponente
Objekt1.Komponente
= 10; Objekt2.Komponente = 20;
= Objekt2.Komponente;
= 30;
07
Objekt1 = new UnsereKlasse ();
Objekt1.Komponente = 60;
= 40;
= 50;
}
}
Gehen Sie das Programm Zeile für Zeile durch und ermitteln Sie den jeweiligen Wert von
Objekt1.Komponente und Objekt2.Komponente.
Lösungsvorschlag:
Zeile
Objekt1.Komponente
01
10
02
20
03
20
04
20
05
40
06
50
07
60
14. – 25. April 2003
Objekt2.Komponente
20
20
30
20
40
50
50
-6-
Sommersemester 2003
Algorithmik II
1. Übung
Rechnerübung 1
Arbeiten mit Java unter Linux
Um mit dem JDE (Java Development Environment) arbeiten zu können, müssen zunächst folgende
Zeilen in die Datei .emacs eingetragen werden:
(setq load-path
(nconc
’(
"/local/jde/lisp"
)
load-path))
(require ’jde)
Java–Programme können nicht unmittelbar gestartet werden. Sie müssen erst mit Hilfe eines Java–
Compilers übersetzt werden:
Dazu muß in der Menüleiste unter dem Menü JDE das Kommando Compile aufgerufen
werden.
Der Java–Compiler erzeugt damit im gleichen Verzeichnis eine ausführbare JAVA-Datei
Ggt.class.
Die class-Datei kann nun mit dem Kommando Run App unter dem Menü JDE ausgeführt werden.
a) Erstellen Sie zunächst im emacs eine Datei Ggt.java mit folgendem Inhalt:
public class Ggt {
public int ggtRekursiv (int a, int b)
{
if( b == 0 )
return a;
else
{
if ( b > a )
return ggtRekursiv(b, a);
else
return ggtRekursiv(b, a-b);
}
}
public static void main (String[] args)
{
Ggt ggtBeispiel = new Ggt();
System.out.println("Der ggT von " + 44
+ " und " + 55 + " ist: "
+ ggtBeispiel.ggtRekursiv(44, 55));
}
}
14. – 25. April 2003
-7-
Sommersemester 2003
Algorithmik II
1. Übung
b) Übersetzen Sie den Inhalt der Datei Ggt.java in ein ausführbares Java–Programm!
Lösungsvorschlag:
Aufruf des Kommandos Compile in der Menüleiste unter dem Menü JDE.
c) Führen Sie das übersetzte Programm aus! Wählen Sie andere Zahlenwerte und übersetzen Sie
jeweils das Programm erneut, um es wieder auszuführen.
d) Es ist lästig, daß die gewünschten Zahlen im Quellcode eingetragen werden müssen. Erweitern Sie daher die main–Funktion um folgende Zeilen:
BufferedReader console
= new BufferedReader(
new InputStreamReader(System.in));
String text1 = new String("");
String text2 = new String("");
try {
System.out.println("Zahl 1 eingeben:");
text1 = console.readLine();
System.out.println("Zahl 2 eingeben:");
text2 = console.readLine();
} catch (IOException e) {};
int zahl1 = Integer.parseInt(text1);
int zahl2 = Integer.parseInt(text2);
und fügen Sie am Beginn import java.io.*; ein.
Es werden nun zwei Strings eingelesen. Die try-catch-Befehle dienen dazu, Probleme
beim Einlesen der Zahlen von der Konsole abzufangen. Sie sollen uns im Moment nicht weiter
interessieren.
Aus den eingelesenen Strings werden im Anschluß die beiden int-Zahlen ermittelt. Verändern
Sie nun die Zeile mit dem Ausgabebefehl so, daß die ggT–Berechnung mit den eingegebenen
Zahlen ausgeführt wird.
Übersetzen Sie das Programm erneut und führen Sie es mit einigen von Ihnen selbst gewählten
anderen Zahlenwerten aus.
Lösungsvorschlag:
System.out.println("Der ggT von " + zahl1
+ " und " + zahl2 + " ist: "
+ ggtBeispiel.ggtRekursiv(zahl1, zahl2));
e) Ändern Sie das Java–Programm in Ihrer Datei Ggt.java so ab, daß bei der Eingabe negative
Zahlen erkannt und zurückgewiesen werden. Das Programm soll so lange erneut zwei Zahlen
einlesen, bis vom Benutzer korrekt zwei positive Zahlen eingegeben wurden.
Denken Sie daran, daß das Programm korrekt beendet oder abgebrochen worden sein muß,
bevor Sie erneut Run App im Menü JDE aufrufen, da sonst der alte Prozeß fortgesetzt wird.
14. – 25. April 2003
-8-
Sommersemester 2003
Algorithmik II
1. Übung
Wollen sie das Programm abbrechen, erreichen Sie dies durch zweimaliges Drücken der Tastenkombination Control-C im Ausführungsfenster.
Lösungsvorschlag: Die Funktion main könnte wie folgt reformuliert werden:
public static void main (String[] args)
{
boolean eingabeOk = false;
BufferedReader console
= new BufferedReader(
new InputStreamReader(System.in));
String text1 = new String("");
String text2 = new String("");
while ( !eingabeOk )
{
try {
System.out.println("Zahl 1 eingeben:");
text1 = console.readLine();
System.out.println("Zahl 2 eingeben:");
text2 = console.readLine();
} catch (IOException e) {};
int zahl1 = Integer.parseInt(Text1);
int zahl2 = Integer.parseInt(Text2);
if( zahl1 < 0 || zahl2 < 0 )
{
System.out.println("Bitte geben Sie zwei
positive ganze Zahlen ein!");
} else
{
Ggt ggtBeispiel = new Ggt();
System.out.println("Der ggT von " + zahl1
+ " und " + zahl2 + " ist: "
+ ggtBeispiel.ggtRekursiv(zahl1, zahl2));
eingabeOk = true;
}
}
}
f) Modifizieren Sie das Java–Programm aus Ggt.java so, daß nicht für jedes Zahlenpaar ein
erneuter Programmaufruf notwendig ist. Dies erreichen Sie zum Beispiel, indem Sie nach der
Ausgabe des Ergebnisses den Benutzer fragen, ob das Programm beendet werden soll.
14. – 25. April 2003
-9-
Sommersemester 2003
Algorithmik II
1. Übung
Hinweis: Strings können in Java mit der Methode boolean equals(String) auf
Gleichheit überprüft werden (s.h. auch Java API-Spezifikation).
Lösungsvorschlag:
Die Funktion main könnte wie folgt erweitert werden:
do {
/* Eingabe der Zahlen */
...
/* Ausgabe des Ergebnisses */
...
System.out.println( "Wollen Sie das Programm beenden? ");
try {
eingabeString = console.readLine();
} catch (IOException e) {};
while ( !eingabeString.equals("ja")
&& !eingabeString.equals("j")
);
Das ist keine vollständige main–Funktion. Es ist hier nur angegeben, wie obiges Programm
um die Abfrage erweitert werden könnte.
g) Ergänzen Sie nun die Klasse Ggt um eine Methode ggtIterativ, die den ggT iterativ
berechnet und führen Sie die Berechnung mit dieser Methode durch.
Lösungsvorschlag:
public int ggtIterativ (int a, int b)
{
int x,y;
x = a;
y = b;
while (x != 0 && y != 0)
{
if(x > y)
x = x - y;
else
y = y - x;
}
return (x + y);
}
h) Spielen“ Sie mit weiteren Java–Programmen aus der Vorlesung oder der Tafelübung.
”
14. – 25. April 2003
- 10 -
Sommersemester 2003
Herunterladen