INFORMATIK-NACHKLAUSUR Name: Bearbeitungszeit: 180 min IF1 − Info 13 GK (GA) Aufgabe 1: 13.01.2003 − Seite 1 − Graphentheorie – Zusammenhang – kürzeste Wege Gegeben ist der rechts abgebildete Graph G. a) Stellen Sie G in Form einer Adjazenzmatrix und in Form einer Adjazenzliste dar. Dabei sollen die Knoten in beiden Darstellungen numerisch sortiert sein. b) Führen Sie auf G von Hand den Algorithmus der BREITENSUCHE (siehe Anlage I) mit Startknoten aus. Veranschaulichen Sie dafür jedes Mal, wenn Sie im Algorithmus die mit { 1 2 50 5 10 10 50 5 10 30 3 6 10 40 10 5 20 4 30 5 7 ∗} markierte Stelle erreichen, den aktuellen Inhalt der Schlange. Zeichnen Sie anschließend den sogenannten „Breitensuchbaum“, der nur die Kanten enthält, die für die BREITENSUCHE benutzt wurden. c) Verwenden Sie nun die TIEFENSUCHE. Veranschaulichen Sie auch hier an gleicher Stelle den aktuellen Inhalt des Stapels. Zeichnen Sie anschließend den „Tiefensuchbaum“. d) Suchen Sie in G die kürzesten Entfernungen vom Startknoten mit Hilfe des Algorithmus von DIJKSTRA (Anlage II). Veranschaulichen Sie dafür jedes Mal, wenn Sie im Algorithmus die mit { ∗} markierte Stelle erreichen, den aktuellen Inhalt der Variablen Distanz und Vorgaenger. e) Nimmt man den Algorithmus der BREITENSUCHE als Grundlage, so lässt sich daraus mit minimalen Änderungen ein Algorithmus erstellen, welcher vom Startknoten ausgehend die kürzeste Entfernung zu allen anderen Knoten im Graphen berechnet. (1) Welche Änderungen müssen lediglich vorgenommen werden? Hinweis: Bitte notieren Sie nur die Änderungen, nicht den ganzen Algorithmus. (2) Die Bedeutungen einiger Variablen haben sich geändert. Erläutern Sie diese im Unterschied zur ursprünglichen Bedeutung. (3) Veranschaulichen Sie Ihren Algorithmus am obigen Beispiel. (4) Die Arbeitsweise dieses Algorithmus ist der des DIJKSTRA-Algorithmus verblüffend ähnlich. Wodurch unterscheiden sich jedoch beide Algorithmen grundlegend? Stichwort: Greedy! (5) Begründen Sie, dass die Laufzeit dieses Algorithmus in der Klasse O(n2) liegt. f) In Anlage III finden Sie einen weiteren Algorithmus, den FORD-Algorithmus, zur Bestimmung des kürzesten Weges. (1) Führen Sie den Algorithmus vom Startknoten ausgehend durch und protokollieren Sie dabei immer dann, wenn Sie die mit { ∗} markierte Stelle erreichen, die aktuelle Variablenbelegung der Felder Distanz und Vorgaenger. (2) Erläutern Sie in eigenen Worten die Arbeitsweise des Algorithmus. Vergleichen Sie die Arbeitsweise sowohl mit dem DIJKSTRA- als auch mit dem aus dem Unterricht bekannten FLOYD-Algorithmus. (3) Begründen Sie, warum der FORD-Algorithmus trotz seiner drei ineinandergeschachtelten Schleifen zur Aufwandsklasse O(n2) zu zählen ist. g) Geben Sie einen Algorithmus an, welcher den längsten Weg in einem Graphen berechnet, der alle Knoten genau einmal enthält. Bestimmen und begründen Sie dessen Aufwandsklasse. 8 INFORMATIK-NACHKLAUSUR Name: Bearbeitungszeit: 180 min IF1 − Info 13 GK (GA) Aufgabe 2: 13.01.2003 − Seite 2 − Graphentheorie − gerichtete Graphen: Kreise Ein gerichteter Graph G heißt kreisfrei, wenn es keinen Weg gibt, dessen Anfangs- und Endknoten gleich sind. a) Geben Sie jeweils ein Beispiel mit mindestens 7 Knoten für einen kreisfreien und einen nicht kreisfreien Graphen an. b) Erläutern Sie, warum die Betrachtung von kreisfreien Graphen auf ungerichteten Graphen unsinnig ist. c) Begründen oder widerlegen Sie: (1) G ist kreisfrei G ist ein Baum (2) G ist ein Baum G ist kreisfrei d) Schreiben Sie einen Algorithmus, welcher auf einem gerichteten Graphen prüft, ob er kreisfrei ist. ALGORITHMUS Input: Output: Lokal: ??? Prüfe_auf_Kreisfreiheit Matrix: kreisfrei: ??? TAdjazenzmatrix boolean { Array[1..n,1..n] of integer } INFORMATIK-NACHKLAUSUR Anlage I zur ALGORITHMUS Input: Output: Lokal: Breitensuche Startknoten: integer Liste: Ergebniskanten: Besucht: Schlange: Zielknoten: { Initialisierung } • Ergebniskanten ← „neue Liste“ • Schlange ← „neue Schlange“ • Für alle Zielknoten tue: • Besucht ← false • Liste[Zielknoten].AnAnfang • Schlange.Enqueue(Startknoten) • Besucht[Startknoten] ← true TAdjazenzliste TLinList array of boolean TQueue integer { über TKantenelement } { über TKnotenelement } { Algorithmus } • Solange NICHT Schlange.Empty tue: • Startknoten ← Schlange.Front • Solange NICHT Liste[Startknoten].AmEnde UND Besucht[Liste[Startknoten].Aktuell] tue: • Liste[Startknoten].Vor • Falls NICHT Besucht[Liste[Startknoten].Aktuell] dann: • Zielknoten ← Liste[Startknoten].Aktuell • Schlange.Enqueue(Zielknoten) • Besucht[Zielknoten] ← true • Ergebniskanten.Einfuegen(Startknoten − Zielknoten) sonst: • Schlange.Dequeue ALGORITHMUS Input: Output: Lokal: Tiefensuche Startknoten: integer Liste: Ergebniskanten: Besucht: Stapel: Zielknoten: TAdjazenzliste TLinList array of boolean TStack integer Ersetze in Breitensuche: Schlange durch Stapel sowie die Methodenaufrufe Enqueue Dequeue Front {∗} durch durch durch Push Pop Top { über TKantenelement } { über TKnotenelement } INFORMATIK-NACHKLAUSUR Anlage II zur ALGORITHMUS Input: Output: Lokal: Dijkstra Matrix: Startknoten: Distanz: Vorgaenger: Erledigt: MinKnoten: Knoten: { Initialisierung } • Für Knoten ← 1 bis n tue: • Distanz[Knoten] ← maxInt • Vorgaenger[Knoten] ← −1 • Erledigt[Knoten] ← false • Distanz[Startknoten] ← 0 TAdjazenzmatrix { Array[1..n,1..n] of integer } integer array[1..n] of integer array[1..n] of integer array[1..n] of boolean integer { hat kleinste Distanz zum Startknoten } integer { durchläuft alle möglichen Knoten } { bedeutet soviel wie: ∞ } { Algorithmus } • Wiederhole n mal: • MinKnoten ← Knoten_mit_kleinster_Distanz {∗} • Falls MinKnoten ≠ −1 dann: • Erledigt[MinKnoten] ← true • Für Knoten ← 1 bis n tue: • Falls NICHT Erledigt[Knoten] UND Distanz[MinKnoten] + Matrix[MinKnoten, Knoten] < Distanz[Knoten] dann: • Distanz[Knoten] ← Distanz[MinKnoten] + Matrix[MinKnoten, Knoten] • Vorgaenger[Knoten] ← MinKnoten Hilfsfunktion zur Bestimmung des Knotens mit minimaler Distanz zum Startknoten: ALGORITHMUS Knoten_mit_kleinster_Distanz Output: MinKnoten: integer { hat kleinste Distanz zum Startknoten } Lokal: MinDistanz: integer Knoten: integer { durchläuft alle möglichen Knoten } • MinDistanz ← maxInt { erst mal von größtmöglicher Distanz ausgehen } • MinKnoten ← −1 • Für Knoten ← 1 bis n tue: • Falls NICHT Erledigt[Knoten] UND Distanz[Knoten] < MinDistanz dann: • MinDistanz ← Distanz[Knoten] • MinKnoten ← Knoten Anlage III zur ALGORITHMUS Input: Output: Lokal: INFORMATIK-NACHKLAUSUR Ford Matrix: TAdjazenzmatrix Startknoten: Distanz: Vorgaenger: AmEnde: von, nach: Knoten: integer array[1..n] of integer array[1..n] of integer boolean integer integer { Array[1..n,1..n] of integer } { Initialisierung } • Für Knoten ← 1 bis n tue: • Distanz[Knoten] ← maxInt • Vorgaenger[Knoten] ← Startknoten • Distanz[Startknoten] ← 0 • Vorgaenger[Startknoten] ← −1 { Algorithmus } • AmEnde ← true • Wiederhole • Für von ← 1 bis n tue: • Für nach ← 1 bis n tue: • Falls Distanz[von] + Matrix[von, nach] < Distanz[nach] dann: • Distanz[nach] ← Distanz[von] + Matrix[von, nach] • Vorgaenger[nach] ← von • AmEnde ← false bis: AmEnde = true {∗}