• Keine Ergebnisse gefunden

Graphen und elementare Algorithmen

N/A
N/A
Protected

Academic year: 2022

Aktie "Graphen und elementare Algorithmen"

Copied!
5
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Graphen und elementare Algorithmen

Es soll ein Programm bzw. eine C-Bibliothek entwickelt werden, die Graphen in Form von Adjazenzmatrizen und Adjazenzlisten unterst¨utzt. Dazu sind die folgenden Funktionalit¨aten zu implementieren:

∙ Aufbau der Datenstrukturen und deren Speicherfreigabe

∙ Hinzuf¨ugen von Kanten und Knoten zu einem Graphen

∙ Z¨ahlen der Kanten eines Graphen

∙ Ausgabe der Datenstrukturen auf die Kommandozeile

∙ Persistenz (Dateioperationen)

∙ Tiefen- und Breitensuche

∙ Uberpr¨ufung der Erreichbarkeit von Knoten in einem Graphen¨

∙ Suchen k¨urzester Wege

Es sind die folgenden Projektphasen zu durchlaufen:

1. Einarbeitung in die Aufgabenstellung

2. Test-First-Programmierung f¨ur alle Funktionsprototypen

∙ Informelle Definition von Testzielen

∙ Aufstellen von Testf¨allen und deren Implementierung 3. Schrittweises Vorgehen f¨ur alle Funktionen

∙ Implementierung

∙ Dokumentation des Quellcodes

∙ Testausf¨uhrung 4. Abschlussdokumentation

∙ 𝐶0-Test mit Gcov, Plug-in f¨ur Eclipse

http://sourceforge.net/projects/gcov-eclipse/

∙ Dokumentation mittels Doxygen (http://www.doxygen.org) generieren

Jeder Teilnehmer soll f¨ur mindestens sechs Funktionen (Test, Implementierung, Dokumen- tation) verantwortlich sein. Dokumentieren Sie im Quellcode entsprechend f¨ur jede Funktion mindestens einen Verantwortlichen. Benutzen Sie daf¨ur das Doxygen-Kommando \author.

(2)

1. Als Einstieg soll eine FiFo-Liste implementiert werden. Sie wird sp¨ater f¨ur die Implemen- tierung einer Breitensuche ben¨otigt. Betrachten Sie dazu die Datei FiFoList.h. Sie enth¨alt bereits die notwendigen Datentypen f¨ur die Liste und deren Elemente. Außerdem existieren schon die Prototypen f¨ur die zu implementierenden Funktionen:

∙ void *dequeue(FiFoList *pList);

L¨oscht den ersten Knoten der Liste und gibt den Zeiger auf die Nutzdaten zur¨uck.

∙ void enqueue(FiFoList *pList, void *pData);

F¨ugt einen Knoten an das Ende der Liste ein.

∙ bool isEmpty(FiFoList *pList);

Pr¨uft, ob die Liste leer ist.

Hinweise:

∙ Die Implementierung der drei Funktionen erfolgt in der Datei FiFoList.c.

∙ Der Datentyp ListElement enth¨alt die Deklaration void *pData, d.h. einen typen- losen Zeiger, der auf die eigentlichen Nutzdaten zeigt. Der Vorteil dieses Konstrukts liegt darin, dass die Liste nicht auf bestimmten Datentyp wie z.B. int-Zahlen fest- gelegt wird. Die Liste ist somit f¨ur jeden beliebigen Datentyp einsetzbar. Allerdings ist beim Aufruf der Liste daf¨ur Sorge zu tragen, dass dynamischer Speicher f¨ur die Nutzdaten anzufordern (vor dem Aufruf vonenqueue) und sp¨ater wieder freizugeben ist (nach einem Aufruf von dequeue). Erst durch entsprechende Castings der Zeiger beschr¨ankt sich die Zeigervariable pData nicht auf bestimmte Datentypen.

2. Betrachten Sie die Datei AdjacencyMatrix.h. Dort gibt es den DatentypadjacencyMatrix zur Darstellung einer Adjazenzmatrix sowie verschiedene Prototypen zur Manipulation einer Adjazenzmatrix. Implementieren Sie zun¨achst die Funktion createAdjMatrix.

Diese soll wie folgt arbeiten:

(a) Anforderung von dynamischem Speicher f¨ur eine adjacencyMatrix (b) Anzahl der Knoten setzen

(c) Aufbau der Matrix mit dynamisch angefordertem Speicher (⇒ ppMatrix) (d) Initialisierung der Matrixeintr¨age

Zur Freigabe des dynamischen Speichers, den eine Adjazenzmatrix belegt, ist außerdem die Funktion freeAdjMatrix zu implementieren.

3. Implementieren Sie zwei Funktionen, die einer Adjazenzmatrix eine neue Kante bzw. einen neuen Knoten hinzuf¨ugen. Die Prototypen sind bereits durch addEdgeToAdjMatrix und addNodeToAdjMatrix gegeben.

Hinweise: Eine Kante (𝑎, 𝑏) wird in der Matrix an der Position ppMatrix[a][b] eingetra- gen. Im Tutorial wurde beschrieben, wie ein eindimensionales Feld dynamisch vergr¨oßert werden kann. Die Erweiterung einer n×n-Matrix auf (n+1)×(n+1) wurde schematisch durch eine Darstellung illustriert – funktioniert aber analog.

(3)

4. Die Funktionen countEdgesInAdjMatrix zum Z¨ahlen der Kanten einer Adjazenzmatrix bzw. eines Graphen und printAdjMatrix zur Ausgabe einer Adjazenzmatrix auf die Kon- sole sind zu implementieren.

5. Es sollen zwei Funktionen implementiert werden, um Adjazenzmatrizen in Dateien schrei- ben und wieder auslesen zu k¨onnen. Die Prototypen sind readAdjMatrixFromFile und writeAdjMatrixToFile.

Eine Adjazenzmatrix soll in der folgenden Form in eine Texdatei geschrieben werden:

∙ die erste Zeile enth¨alt die Anzahl der Knoten

∙ jede weitere Zeile entspricht einer Zeile der Matrix

∙ die Eintr¨age einer Zeile werden durch ein Leerzeichen getrennt Tabelle 1 enth¨alt einen Beispielgraphen mit 5 Knoten und 6 Kanten.

Tabelle 1: Dateiformat einer Adjazenzmatrix 5

0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1

6. Implementieren Sie die Funktion depthFirstSearch, die rekursiv eine Tiefensuche auf einem Graphen bzw. der Adjazenzmatrix durchf¨uhrt.

Hinweis: Die Implementierung soll anhand des Pseudocodes zur Tiefensuche aus dem Tu- torial erfolgen.

7. Betrachten Sie die Datei AdjacencyList.h. Sie enth¨alt f¨ur eine Adjazenzliste die Datentypen node und adjacencyList. In Abbildung 1 ist ein Beispiel zu sehen, wie eine Adjazenzliste realisiert wird.

Implementieren Sie die folgenden Funktionen zur Manipulation einer Adjazenzliste:

adjacencyList *createAdjList(int numberOfNodes);

void freeAdjList(adjacencyList *pAdjList);

void addEdgeToAdjList(adjacencyList *pAdjList, int startnode, int endnode);

int addNodeToAdjList(adjacencyList *pAdjList);

int countEdgesInAdjList(adjacencyList *pAdjList);

void printAdjList(adjacencyList *pAdjList);

Hinweis: Die Implementierung soll in der Datei AdjacencyList.c erfolgen.

(4)

Abbildung 1: Adjazenzliste

8. Implementieren Sie eine Breitensuche, die auf einer Adjazenzliste arbeitet. Daf¨ur ist der Prototyp breadthFirstSearch zu benutzen.

Hinweis: F¨uhren Sie die Implementierung anhand des Pseudocodes aus dem Tutorial durch.

9. In der Datei tools.h gibt es die Prototypen createAdjMatrixFromList und

createAdjListFromMatrix. Implementieren sie jeweils die Funktionen, um aus einer Ad- jazenzmatrix eine Adjazenzliste zu erzeugen und umgekehrt.

10. Es sind zwei Funktionen in der Datei tools.c zu implementieren, die die implementierte Tiefen- und Breitensuche benutzen, um f¨ur einen gegebenen Knoten 𝑎 eines Graphen zu pr¨ufen, ob alle anderen Knoten durch Wege erreichbar sind.

Die Funktion checkReachabilityMatrixsoll mittels der Tiefensuche arbeiten – die Funk- tion checkReachabilityList hingegen soll die Breitensuche benutzen.

Die Datei Graph.zip bzw. Graph.txt enth¨alt einen Graphen mit 1000 Knoten. F¨uhren Sie einen Erreichbarkeitscheck f¨ur den Knoten mit Index 0 mit beiden Funktionen aus.

11. Implementieren Sie in der Datei tools.c die Funktion pathCheck, die f¨ur zwei gegebene Knoten 𝑎 und 𝑏 pr¨uft, ob ein Weg von Knoten 𝑎 zum Knoten𝑏 existiert.

12. Implementieren Sie in der Datei tools.c die FunktionfindShortestPath, die f¨ur zwei gege- bene Knoten𝑎 und 𝑏einen k¨urzesten Weg von 𝑎 nach𝑏berechnet und ihn auf die Konsole ausgibt, sofern vorhanden. Benutzen Sie f¨ur die Wegesuche eine Breitensuche unter der Annahme, dass jede Kante des Graphen die Gewichtung 1 besitzt.

13. Wandeln Sie den Graphen aus der Datei Graph.txt mittels der FunktionwriteGraphMLFile in das Format GraphML um. ¨Offnen Sie die neu erzeugte Datei mit der Software yEd (http://www.yworks.com/de/products_yed_about.htm) und probieren Sie verschiedene Layouts zur Darstellung des Graphen aus.

(5)

Programmierkonventionen:

∙ Tragen Sie zu Beginn jeder c-Datei einen Kommentar ein, der folgende Form hat:

/***********************************************

* Datei: filename.c *

* Gruppe X: Axel Hollmann 7654321 *

* Michael Linschulte 1212121 *

* Sascha Padberg 1234567 *

* Datum: 30.03.2010 *

* Beschreibung: Beschreibung der Datei *

***********************************************/

∙ Bezeichner:

– werden funktionsgerecht in Englisch benannt

– beginnen mit einem Kleinbuchstaben und bestehen aus mindestens 3 Buchstaben (Ausnahmen bilden Z¨ahlvariablen wie z.B. i, k, l, n)

– bei Variablen, die aus mehreren W¨ortern zusammengesetzt sind, werden die Worte ohne Unterstrich zusammengesetzt und jeweils die weiteren Anfangsbuchstaben groß geschrieben

Bsp.: int positionX, nextValue;

– Zeigervariablen: f¨ur jeden Stern wird ein 𝑝an den Anfang gesetzt (Bsp.: int *pInt; char **ppMatrix;)

∙ Makros bestehen nur aus Großbuchstaben

∙ Kommentare:

Der Quellcode ist sorgf¨altig zu kommentieren. Die Prototypen in den Header-Dateien sind bereits mit Doxygen dokumentiert.

∙ Einr¨uckungen:

Einr¨uckungen bestehen aus 4 Leerzeichen. Geschweifte Klammern, die zusammengeh¨oren, stehen auf einer Senkrechten:

if(...) {

...

}

Referenzen

ÄHNLICHE DOKUMENTE

Für einen Knoten eines Graphen ist der Grad definiert als die Anzahl der mit inzidenten Kanten.. Für einen Knoten eines Digraphen definieren wir den Ausgangsgrad

Wenn dieser Eintrag (nennen wir ihn ) in der ersten Zeile aufgezeichnet wird, dann sind alle vorherigen Knoten in der ersten Zeile gelöscht,.

Wir haben gezeigt (Satz 11), dass eine Abbildung genau dann ein maximaler - -Fluss im Flussnetz ist, wenn sie die folgenden Eigenschaften erfüllt:. es gibt keinen

Ein schlichter Graph ist genau dann -fach zusammenhängend, wenn für jedes Knotenpaar von , , mindestens paarweise innerlich disjunkte - -Wege

Bemerkung: Da in einem Weg die Kanten per Definition paarweise verschieden sind, enthält ein Eulerscher Weg damit jede Kante genau einmal.. G = (V, E)

Bemerkung: Da abgesehen vom Endknoten kein Knoten wiederholt wird, enthält auch ein Hamiltonscher Zyklus jeden Knoten von genau einmal.. Hamiltonsche Graphen sind benannt nach

Ist ein Knoten des Graphen ein Endknoten einer Kante im Matching , dann wird als -gesättigt bezeichnet...

Wenn die Nachbarn von weniger als Farben verbrauchen, dann kann mit einer nicht verbrauchten Farbe gefärbt werden... Satz von