Prof. Dr. R. Schrader mit V. Weil und D. Herrmann SS 2009 1. Übung zum Programmierpraktikum 21. April – 04. Mai 2009 OHNE ABGABE Aufgabe Implementieren Sie den Algorithmus von Dijkstra zur Ermittlung kürzester Wege auf einem Graphen in Java oder C++. Die Datenstruktur können Sie frei wählen. Achten Sie jedoch darauf, dass Sie Ihr Programm möglichst offen für andere Datenstrukturen halten, da in dem Praktikums-Skript verschiedene Datenstrukturen vorgestellt werden, von denen Sie einige implementieren sollen. In dieser 1. Übung wird es darum gehen, die notwendigen Funktionen zu programmieren, die Sie später wieder benutzen können. Für die Modularität des Programms wäre es von Vorteil, wenn Sie sich das Konzept eines Interface und der damit verbundenen Vererbung genauer ansehen würden. Die Idee dahinter ist, dass Sie einige für das Programm immer benötigte Befehle deklarieren und diese dann in jeder Ihrer Datenstrukturklassen verwenden. Auf diese Weise sind Änderungen am Kern des Codes nicht mehr notwendig. Eine kleine Änderung in der Initialisierung des Programms würde somit vollkommen ausreichen, um weitere Datenstrukturen in Ihren bestehenden Code zu integrieren oder es komplett von einer Datenstruktur A auf eine andere Datenstruktur B umzustellen. Tipps für das Vorgehen a) Überlegen Sie sich zunächst eine geeignete Datenstruktur, in der Sie den Graphen abspeichern, z.B. eine Adjazenzmatrix. b) Schreiben Sie eine Funktion/Methode, mit der Sie die Eingabedaten aus einer Datei mit dem Namen input.txt einlesen und in Ihrer Struktur abspeichern können. (Details dazu weiter unten.) c) Überlegen Sie sich dann eine Datenstruktur, in der Sie die Front der Kürzeste–Wege–Menge behandeln, z.B. eine verkettete Liste. d) Programmieren Sie den im Skript besprochenen Algorithmus von Dijkstra zur Berechnung eines kürzesten Weges. e) Um die Laufzeiten unter Verwendung verschiedener Datenstrukturen zu vergleichen, können Sie eine Systemzeit-Messfunktion benutzen. Eine Erklärung finden Sie weiter unten. f) Ihr Programm sollte die ermittelte Distanz als reellwertige Zahl in eine Datei mit dem Namen output.txt ausgeben. Datenformat Wir stellen Ihnen Testdaten auf den Webseiten zur Vorlesung bereit. Alle Eingabedaten haben das folgende Format: Zeile 1. 2. 3. 4. 5. - (m+4). Inhalt Anzahl Knoten (= n) Anzahl Kanten (= m) Startknoten (eine Zahl ∈ {1, . . . , n}) Zielknoten (eine Zahl ∈ {1, . . . , n}) gerichtete Kante im Format v1:v2:Gewicht Alle Zeilen sind durch einfache Zeilenumbrüche (\n) getrennt. Die Zeilen 5 bis m + 4 enthalten alle gerichteten Kanten des beschriebenen Graphen: Die Knoten v1, v2 sind Zahlen zwischen 1 und n. Das Gewicht der Kante ist eine Zahl aus N+ . Die drei Werte sind durch einen Doppelpunkt getrennt. Laufzeit Alle technischen Hinweise beziehen sich in Zukunft primär auf die Programmiersprache Java. C++ stellt andere Funktionen bereit. Die von unserer Seite angebotenen Hilfestellungen auf diesem Übungszettel belaufen sich dennoch auf beide erwähnten Programmiersprachen. Das Standard–Java–SDK bietet die Möglichkeit, die Zeit, die Ihr Programm benötigt, zu messen. Dazu importieren Sie die folgende Klasse mit dem Befehl import java.lang.System; in Ihr bestehendes Programm. Sie haben nun mit der Funktion System.currentTimeMillis() die Möglichkeit, die aktuelle Systemzeit in Millisekunden in einer Variable vom Typ long zu speichern. Um die Laufzeit Ihres Algorithmus zu messen, sollten Sie VOR und NACH dem Algorithmus die Zeit Ihres Systems nehmen, diese voneinander subtrahieren und in geeigneter Form abspeichern / weiterverwenden / ausgeben. Sollte die oben erwähnte Funktion Ihren Ansprüchen nicht genügen, wenn z.B. Ihr Programm schneller läuft als es gemessen werden kann, so können Sie auch auf die Funktion System.nanoTime() ausweichen. Näheres hierzu entnehmen Sie bitte aus der Java API. Auch C++ stellt Funktionen zur Zeitmessung zur Verfügung. Binden Sie dafür die Headerdatei time.h in Ihr Programm ein. Eine Möglichkeit ist, mit clock t begin = clock(); die Zeit vor Beginn des Algorithmus zu messen, und durch clock t ende = clock(); die Zeitmessung zu beenden. Anschließend kann durch Berechnung der Differenzzeit, beispielsweise durch clock t diffticks = ende - begin; double diff = diffticks/CLOCKS PER SEC; die benötigte Zeit errechnet werden. Organisatorisches • Diese erste Übung dient dazu, dass Sie sich mit den Strukturen und grundlegenden Funktionen vertraut machen und wird von uns nicht kontrolliert. Die zweite und dritte Übung soll jedoch über das Internet (entsprechende Seiten werden noch eingerichtet) abgegeben werden. Ihr Quelltext wird dann (wie in den Übungen zu Informatik 2) einer automatischen Prüfung unterzogen und Sie erhalten sofort eine Rückmeldung, ob sich Ihr Programm kompilieren ließ. Bitte beachten Sie dazu folgende Hinweise: Allgemein: – Der Quelltext muss in einer einzigen Datei enthalten sein. – Die Eingabe wird über die Datei input.txt gelesen und die Ausgabe Ihres Programmes muss in eine Datei output.txt geschrieben werden. Beachten Sie die Kleinschreibung! Die Dateinamen sollten fest in Ihrem Quelltext verankert sein (d.h. nicht über Eingabezeilen gelesen werden o.ä.). – Sie können Ausgaben auf dem Standardausgabekanal ( Bildschirm“) machen. Die” se fließen nicht in die Kontrolle ein. Bei einem Fehler wird Ihnen diese Ausgabe jedoch angezeigt, so dass Sie sie nutzen können, um diesen zu beheben. für Java Programme: – Es werden nur Java Programme zugelassen, die mit JDK 1.5 oder niedriger kompilierbar und lauffähig sind. Ihr Quellcode kann mehrere Dateien umfassen (z.B. eine Datei pro Klasse). – Benutzen Sie keine Oberflächen-Klassen (z.B. AWT/Swing). Diese werden zu Fehlern beim automatischen Testen führen. für C++ Programme: – Ihr Programm wird auf einem Unix–Rechner mittels des Programms gcc kompiliert. Dadurch kann es zu kleineren Unstimmigkeiten mit Windows–Compilern kommen. Versuchen Sie sich deswegen so gut wie möglich an den ANSI–C(++) Standard zu halten. – Sie dürfen die Standard Template Library (STL) benutzen (C++). – Achten Sie darauf, dass Sie keine in C++ geschützten Begriffe verwenden. Solche geschützten Begriffe sind u.a. new, delete, class, etc. • Für die Abgaben der kommenden Übungen: Sie dürfen alleine, aber auch in einer Gruppe von bis zu 3 Personen zusammenarbeiten. Pro Gruppe (ob sie jetzt aus einer, zwei oder drei Personen besteht) erwarten wir genau eine Abgabe, auf der genau vermerkt ist, wer an der Programmierung teilgenommen hat (Name, Vorname, Matrikelnummer). Namen, die auf mehreren Abgaben derselben Aufgabe auftauchen, erhalten 0 Punkte, da wir davon ausgehen müssen, dass der Name nur mit draufgeschrieben“ wurde. Wir kontrollieren abgegebene ” Übungen auf ähnliche Kopien. Bei Täuschungsversuchen werden beide betroffenen Gruppen mit 0 bewertet. • Ihr Programm wird nicht nur automatisch, sondern zusätzlich von Hand“ durchgeschaut. ” Achten Sie bitte deswegen auf: – eine ausführliche Kommentierung – intuitiv verständliche Namensgebung bei Variablen und Funktionen – übersichtliches Einrücken des Quelltextes, so dass die verschiedenen Texttiefen logische Arbeitsabläufe des Programms verdeutlichen Auch diese Aspekte fließen in die Bewertung ein! • Webseite zur Veranstaltung http://www.zaik.uni-koeln.de/AFS/teachings/ss09/ProgPrakt/ • Wir haben eine Mailingliste eingerichtet, auf der sich alle Teilnehmer eintragen können. Sie soll dazu genutzt werden, von uns aus an Sie wichtige Informationen weiterleiten zu können. Die Adresse zur Anmeldung lautet: http://www.zpr.uni-koeln.de/mailman/listinfo/progprakt2009