commit 8bce97f6532edbdd412a390d2bce9e8081604add Author: Jonas Neugebauer Date: Sun Jan 10 23:51:46 2021 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fe8940 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# ---> Java +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt +Dokumente* + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + diff --git a/Edge.java b/Edge.java new file mode 100755 index 0000000..1d33776 --- /dev/null +++ b/Edge.java @@ -0,0 +1,75 @@ +/** + *

+ * Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018 + *

+ *

+ * Klasse Edge + *

+ *

+ * Die Klasse Edge stellt eine einzelne, ungerichtete Kante eines Graphen dar. + * Beim Erstellen werden die beiden durch sie zu verbindenden Knotenobjekte und eine + * Gewichtung als double uebergeben. Beide Knotenobjekte koennen abgefragt werden. + * Des Weiteren koennen die Gewichtung und eine Markierung gesetzt und abgefragt werden. + *

+ * + * @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule + * @version Oktober 2015 + */ +public class Edge{ + private Vertex[] vertices; + private double weight; + private boolean mark; + + /** + * Ein neues Objekt vom Typ Edge wird erstellt. Die von diesem Objekt + * repraesentierte Kante verbindet die Knoten pVertex und pAnotherVertex mit der + * Gewichtung pWeight. Ihre Markierung hat den Wert false. + */ + public Edge(Vertex pVertex, Vertex pAnotherVertex, double pWeight){ + vertices = new Vertex[2]; + vertices[0] = pVertex; + vertices[1] = pAnotherVertex; + weight = pWeight; + mark = false; + } + + /** + * Die Anfrage gibt die beiden Knoten, die durch die Kante verbunden werden, als neues Feld vom Typ Vertex zurueck. Das Feld hat + * genau zwei Eintraege mit den Indexwerten 0 und 1. + */ + public Vertex[] getVertices(){ + Vertex[] result = new Vertex[2]; + result[0] = vertices[0]; + result[1] = vertices[1]; + return result; + } + + /** + * Der Auftrag setzt das Gewicht der Kante auf pWeight. + */ + public void setWeight(double pWeight){ + weight = pWeight; + } + + /** + * Die Anfrage liefert das Gewicht der Kante als double. + */ + public double getWeight(){ + return weight; + } + + /** + * Der Auftrag setzt die Markierung der Kante auf den Wert pMark. + */ + public void setMark(boolean pMark){ + mark = pMark; + } + + /** + * Die Anfrage liefert true, wenn die Markierung der Kante den Wert true hat, ansonsten false. + */ + public boolean isMarked(){ + return mark; + } + +} diff --git a/Graph.java b/Graph.java new file mode 100755 index 0000000..43a8109 --- /dev/null +++ b/Graph.java @@ -0,0 +1,312 @@ +/** + *

+ * Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018 + *

+ *

+ * Klasse Graph + *

+ *

+ * Die Klasse Graph stellt einen ungerichteten, kantengewichteten Graphen dar. Es koennen + * Knoten- und Kantenobjekte hinzugefuegt und entfernt, flache Kopien der Knoten- und Kantenlisten + * des Graphen angefragt und Markierungen von Knoten und Kanten gesetzt und ueberprueft werden. + * Des Weiteren kann eine Liste der Nachbarn eines bestimmten Knoten, eine Liste der inzidenten + * Kanten eines bestimmten Knoten und die Kante von einem bestimmten Knoten zu einem + * anderen bestimmten Knoten angefragt werden. Abgesehen davon kann abgefragt werden, welches + * Knotenobjekt zu einer bestimmten ID gehoert und ob der Graph leer ist. + *

+ * + * @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule + * @version Oktober 2015 + */ +public class Graph{ + private List vertices; + private List edges; + + /** + * Ein Objekt vom Typ Graph wird erstellt. Der von diesem Objekt + * repraesentierte Graph ist leer. + */ + public Graph(){ + //Leere Listen fuer Knoten und Kanten erstellen. + vertices = new List(); + edges = new List(); + } + + /** + * Die Anfrage liefert eine neue Liste aller Knotenobjekte vom Typ List. + */ + public List getVertices(){ + //Eine neue Liste mit allen Vertex-Objekten erstellen. + List result = new List(); + vertices.toFirst(); + while (vertices.hasAccess()){ + result.append(vertices.getContent()); + vertices.next(); + } + //Aktuelles Element zum Anfang bewegen. + result.toFirst(); + + return result; + } + + /** + * Die Anfrage liefert eine neue Liste aller Kantenobjekte vom Typ List. + */ + public List getEdges(){ + //Eine neue Liste mit allen Edge-Objekten erstellen. + List result = new List(); + edges.toFirst(); + while (edges.hasAccess()){ + result.append(edges.getContent()); + edges.next(); + } + //Aktuelles Element zum Anfang bewegen. + result.toFirst(); + + return result; + } + + /** + * Die Anfrage liefert das Knotenobjekt mit pID als ID. Ist ein solchen Knotenobjekt nicht im Graphen enthalten, + * wird null zurueckgeliefert. + */ + public Vertex getVertex(String pID){ + //Vertex-Objekt mit pID als ID suchen. + Vertex result = null; + vertices.toFirst(); + while (vertices.hasAccess() && result == null){ + if (vertices.getContent().getID().equals(pID)){ + result = vertices.getContent(); + } + vertices.next(); + } + + //Objekt zurueckliefern. + return result; + } + + /** + * Der Auftrag fuegt den Knoten pVertex in den Graphen ein, sofern es noch keinen + * Knoten mit demselben ID-Eintrag wie pVertex im Graphen gibt und pVertex eine ID ungleich null hat. + * Ansonsten passiert nichts. + */ + public void addVertex(Vertex pVertex){ + //Pruefen, ob der Vertex existiert und eine ID hat. + if (pVertex != null && pVertex.getID() != null) { + //Pruefen, ob nicht schon ein Vertex mit gleicher ID enthalten ist. + boolean freeID = true; + vertices.toFirst(); + while (vertices.hasAccess() && freeID){ + if (vertices.getContent().getID().equals(pVertex.getID())){ + freeID = false; + } + vertices.next(); + } + + //Wenn die ID noch frei ist, den Vertex einfuegen, sonst nichts tun. + if (freeID) { + vertices.append(pVertex); + } + } + } + + /** + * Der Auftrag fuegt die Kante pEdge in den Graphen ein, sofern beide durch die Kante verbundenen Knoten + * im Graphen enthalten sind, nicht identisch sind und noch keine Kante zwischen den Knoten existiert. Ansonsten passiert nichts. + */ + public void addEdge(Edge pEdge){ + //Pruefen, ob pEdge exisitert. + if (pEdge != null){ + Vertex[] vertexPair = pEdge.getVertices(); + + //Einfuegekriterien pruefen. + if (vertexPair[0] != null && vertexPair[1] != null && + this.getVertex(vertexPair[0].getID()) == vertexPair[0] && + this.getVertex(vertexPair[1].getID()) == vertexPair[1] && + this.getEdge(vertexPair[0], vertexPair[1]) == null && + vertexPair[0] != vertexPair[1]){ + //Kante einfuegen. + edges.append(pEdge); + } + } + } + + /** + * Der Auftrag entfernt den Knoten pVertex aus dem Graphen und loescht alle Kanten, die mit ihm inzident sind. + * Ist der Knoten pVertex nicht im Graphen enthalten, passiert nichts. + */ + public void removeVertex(Vertex pVertex){ + //Inzidente Kanten entfernen. + edges.toFirst(); + while (edges.hasAccess()){ + Vertex[] akt = edges.getContent().getVertices(); + if (akt[0] == pVertex || akt[1] == pVertex){ + edges.remove(); + } else { + edges.next(); + } + } + + //Knoten entfernen + vertices.toFirst(); + while (vertices.hasAccess() && vertices.getContent()!= pVertex){ + vertices.next(); + } + if (vertices.hasAccess()){ + vertices.remove(); + } + } + + /** + * Der Auftrag entfernt die Kante pEdge aus dem Graphen. Ist die Kante pEdge nicht + * im Graphen enthalten, passiert nichts. + */ + public void removeEdge(Edge pEdge){ + //Kante aus Kantenliste des Graphen entfernen. + edges.toFirst(); + while (edges.hasAccess()){ + if (edges.getContent() == pEdge){ + edges.remove(); + } else { + edges.next(); + } + } + } + + /** + * Der Auftrag setzt die Markierungen aller Knoten des Graphen auf pMark. + */ + public void setAllVertexMarks(boolean pMark){ + vertices.toFirst(); + while (vertices.hasAccess()){ + vertices.getContent().setMark(pMark); + vertices.next(); + } + } + + /** + * Der Auftrag setzt die Markierungen aller Kanten des Graphen auf pMark. + */ + public void setAllEdgeMarks(boolean pMark){ + edges.toFirst(); + while (edges.hasAccess()){ + edges.getContent().setMark(pMark); + edges.next(); + } + } + + /** + * Die Anfrage liefert true, wenn alle Knoten des Graphen mit true markiert sind, ansonsten false. + */ + public boolean allVerticesMarked(){ + boolean result = true; + vertices.toFirst(); + while (vertices.hasAccess()){ + if (!vertices.getContent().isMarked()){ + result = false; + } + vertices.next(); + } + return result; + } + + /** + * Die Anfrage liefert true, wenn alle Kanten des Graphen mit true markiert sind, ansonsten false. + */ + public boolean allEdgesMarked(){ + boolean result = true; + edges.toFirst(); + while (edges.hasAccess()){ + if (!edges.getContent().isMarked()){ + result = false; + } + edges.next(); + } + return result; + } + + /** + * Die Anfrage liefert alle Nachbarn des Knotens pVertex als neue Liste vom Typ List. Hat der Knoten + * pVertex keine Nachbarn in diesem Graphen oder ist gar nicht in diesem Graphen enthalten, so + * wird eine leere Liste zurueckgeliefert. + */ + public List getNeighbours(Vertex pVertex){ + List result = new List(); + + //Alle Kanten durchlaufen. + edges.toFirst(); + while (edges.hasAccess()){ + + //Wenn ein Knoten der Kante pVertex ist, den anderen als Nachbarn in die Ergebnisliste einfuegen. + Vertex[] vertexPair = edges.getContent().getVertices(); + if (vertexPair[0] == pVertex) { + result.append(vertexPair[1]); + } else { + if (vertexPair[1] == pVertex){ + result.append(vertexPair[0]); + } + } + edges.next(); + } + return result; + } + + /** + * Die Anfrage liefert eine neue Liste alle inzidenten Kanten zum Knoten pVertex. Hat der Knoten + * pVertex keine inzidenten Kanten in diesem Graphen oder ist gar nicht in diesem Graphen enthalten, so + * wird eine leere Liste zurueckgeliefert. + */ + public List getEdges(Vertex pVertex){ + List result = new List(); + + //Alle Kanten durchlaufen. + edges.toFirst(); + while (edges.hasAccess()){ + + //Wenn ein Knoten der Kante pVertex ist, dann Kante als inzidente Kante in die Ergebnisliste einfuegen. + Vertex[] vertexPair = edges.getContent().getVertices(); + if (vertexPair[0] == pVertex) { + result.append(edges.getContent()); + } else{ + if (vertexPair[1] == pVertex){ + result.append(edges.getContent()); + } + } + edges.next(); + } + return result; + } + + /** + * Die Anfrage liefert die Kante, welche die Knoten pVertex und pAnotherVertex verbindet, + * als Objekt vom Typ Edge. Ist der Knoten pVertex oder der Knoten pAnotherVertex nicht + * im Graphen enthalten oder gibt es keine Kante, die beide Knoten verbindet, so wird null + * zurueckgeliefert. + */ + public Edge getEdge(Vertex pVertex, Vertex pAnotherVertex){ + Edge result = null; + + //Kanten durchsuchen, solange keine passende gefunden wurde. + edges.toFirst(); + while (edges.hasAccess() && result == null){ + + //Pruefen, ob die Kante pVertex und pAnotherVertex verbindet. + Vertex[] vertexPair = edges.getContent().getVertices(); + if ((vertexPair[0] == pVertex && vertexPair[1] == pAnotherVertex) || + (vertexPair[0] == pAnotherVertex && vertexPair[1] == pVertex)) { + //Kante als Ergebnis merken. + result = edges.getContent(); + } + edges.next(); + } + return result; + } + + /** + * Die Anfrage liefert true, wenn der Graph keine Knoten enthaelt, ansonsten false. + */ + public boolean isEmpty(){ + return vertices.isEmpty(); + } + +} diff --git a/List.java b/List.java new file mode 100755 index 0000000..8c82b92 --- /dev/null +++ b/List.java @@ -0,0 +1,345 @@ + /** + *

+ * Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018 + *

+ *

+ * Generische Klasse List + *

+ *

+ * Objekt der generischen Klasse List verwalten beliebig viele linear + * angeordnete Objekte vom Typ ContentType. Auf hoechstens ein Listenobjekt, + * aktuellesObjekt genannt, kann jeweils zugegriffen werden.
+ * Wenn eine Liste leer ist, vollstaendig durchlaufen wurde oder das aktuelle + * Objekt am Ende der Liste geloescht wurde, gibt es kein aktuelles Objekt.
+ * Das erste oder das letzte Objekt einer Liste koennen durch einen Auftrag zum + * aktuellen Objekt gemacht werden. Ausserdem kann das dem aktuellen Objekt + * folgende Listenobjekt zum neuen aktuellen Objekt werden.
+ * Das aktuelle Objekt kann gelesen, veraendert oder geloescht werden. Ausserdem + * kann vor dem aktuellen Objekt ein Listenobjekt eingefuegt werden. + *

+ * + * @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule + * @version Generisch_06 2015-10-25 + */ +public class List { + + /* --------- Anfang der privaten inneren Klasse -------------- */ + + private class ListNode { + + private ContentType contentObject; + private ListNode next; + + /** + * Ein neues Objekt wird erschaffen. Der Verweis ist leer. + * + * @param pContent das Inhaltsobjekt vom Typ ContentType + */ + private ListNode(ContentType pContent) { + contentObject = pContent; + next = null; + } + + /** + * Der Inhalt des Knotens wird zurueckgeliefert. + * + * @return das Inhaltsobjekt des Knotens + */ + public ContentType getContentObject() { + return contentObject; + } + + /** + * Der Inhalt dieses Kontens wird gesetzt. + * + * @param pContent das Inhaltsobjekt vom Typ ContentType + */ + public void setContentObject(ContentType pContent) { + contentObject = pContent; + } + + /** + * Der Nachfolgeknoten wird zurueckgeliefert. + * + * @return das Objekt, auf das der aktuelle Verweis zeigt + */ + public ListNode getNextNode() { + return this.next; + } + + /** + * Der Verweis wird auf das Objekt, das als Parameter uebergeben + * wird, gesetzt. + * + * @param pNext der Nachfolger des Knotens + */ + public void setNextNode(ListNode pNext) { + this.next = pNext; + } + + } + + /* ----------- Ende der privaten inneren Klasse -------------- */ + + // erstes Element der Liste + ListNode first; + + // letztes Element der Liste + ListNode last; + + // aktuelles Element der Liste + ListNode current; + + /** + * Eine leere Liste wird erzeugt. + */ + public List() { + first = null; + last = null; + current = null; + } + + /** + * Die Anfrage liefert den Wert true, wenn die Liste keine Objekte enthaelt, + * sonst liefert sie den Wert false. + * + * @return true, wenn die Liste leer ist, sonst false + */ + public boolean isEmpty() { + // Die Liste ist leer, wenn es kein erstes Element gibt. + return first == null; + } + + /** + * Die Anfrage liefert den Wert true, wenn es ein aktuelles Objekt gibt, + * sonst liefert sie den Wert false. + * + * @return true, falls Zugriff moeglich, sonst false + */ + public boolean hasAccess() { + // Es gibt keinen Zugriff, wenn current auf kein Element verweist. + return current != null; + } + + /** + * Falls die Liste nicht leer ist, es ein aktuelles Objekt gibt und dieses + * nicht das letzte Objekt der Liste ist, wird das dem aktuellen Objekt in + * der Liste folgende Objekt zum aktuellen Objekt, andernfalls gibt es nach + * Ausfuehrung des Auftrags kein aktuelles Objekt, d.h. hasAccess() liefert + * den Wert false. + */ + public void next() { + if (this.hasAccess()) { + current = current.getNextNode(); + } + } + + /** + * Falls die Liste nicht leer ist, wird das erste Objekt der Liste aktuelles + * Objekt. Ist die Liste leer, geschieht nichts. + */ + public void toFirst() { + if (!isEmpty()) { + current = first; + } + } + + /** + * Falls die Liste nicht leer ist, wird das letzte Objekt der Liste + * aktuelles Objekt. Ist die Liste leer, geschieht nichts. + */ + public void toLast() { + if (!isEmpty()) { + current = last; + } + } + + /** + * Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das + * aktuelle Objekt zurueckgegeben, andernfalls (hasAccess() == false) gibt + * die Anfrage den Wert null zurueck. + * + * @return das aktuelle Objekt (vom Typ ContentType) oder null, wenn es + * kein aktuelles Objekt gibt + */ + public ContentType getContent() { + if (this.hasAccess()) { + return current.getContentObject(); + } else { + return null; + } + } + + /** + * Falls es ein aktuelles Objekt gibt (hasAccess() == true) und pContent + * ungleich null ist, wird das aktuelle Objekt durch pContent ersetzt. Sonst + * geschieht nichts. + * + * @param pContent + * das zu schreibende Objekt vom Typ ContentType + */ + public void setContent(ContentType pContent) { + // Nichts tun, wenn es keinen Inhalt oder kein aktuelles Element gibt. + if (pContent != null && this.hasAccess()) { + current.setContentObject(pContent); + } + } + + /** + * Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird ein neues + * Objekt vor dem aktuellen Objekt in die Liste eingefuegt. Das aktuelle + * Objekt bleibt unveraendert.
+ * Wenn die Liste leer ist, wird pContent in die Liste eingefuegt und es + * gibt weiterhin kein aktuelles Objekt (hasAccess() == false).
+ * Falls es kein aktuelles Objekt gibt (hasAccess() == false) und die Liste + * nicht leer ist oder pContent gleich null ist, geschieht nichts. + * + * @param pContent + * das einzufuegende Objekt vom Typ ContentType + */ + public void insert(ContentType pContent) { + if (pContent != null) { // Nichts tun, wenn es keinen Inhalt gibt. + if (this.hasAccess()) { // Fall: Es gibt ein aktuelles Element. + + // Neuen Knoten erstellen. + ListNode newNode = new ListNode(pContent); + + if (current != first) { // Fall: Nicht an erster Stelle einfuegen. + ListNode previous = this.getPrevious(current); + newNode.setNextNode(previous.getNextNode()); + previous.setNextNode(newNode); + } else { // Fall: An erster Stelle einfuegen. + newNode.setNextNode(first); + first = newNode; + } + + } else { //Fall: Es gibt kein aktuelles Element. + + if (this.isEmpty()) { // Fall: In leere Liste einfuegen. + + // Neuen Knoten erstellen. + ListNode newNode = new ListNode(pContent); + + first = newNode; + last = newNode; + } + + } + } + } + + /** + * Falls pContent gleich null ist, geschieht nichts.
+ * Ansonsten wird ein neues Objekt pContent am Ende der Liste eingefuegt. + * Das aktuelle Objekt bleibt unveraendert.
+ * Wenn die Liste leer ist, wird das Objekt pContent in die Liste eingefuegt + * und es gibt weiterhin kein aktuelles Objekt (hasAccess() == false). + * + * @param pContent + * das anzuhaengende Objekt vom Typ ContentType + */ + public void append(ContentType pContent) { + if (pContent != null) { // Nichts tun, wenn es keine Inhalt gibt. + + if (this.isEmpty()) { // Fall: An leere Liste anfuegen. + this.insert(pContent); + } else { // Fall: An nicht-leere Liste anfuegen. + + // Neuen Knoten erstellen. + ListNode newNode = new ListNode(pContent); + + last.setNextNode(newNode); + last = newNode; // Letzten Knoten aktualisieren. + } + + } + } + + /** + * Falls es sich bei der Liste und pList um dasselbe Objekt handelt, + * pList null oder eine leere Liste ist, geschieht nichts.
+ * Ansonsten wird die Liste pList an die aktuelle Liste angehaengt. + * Anschliessend wird pList eine leere Liste. Das aktuelle Objekt bleibt + * unveraendert. Insbesondere bleibt hasAccess identisch. + * + * @param pList + * die am Ende anzuhaengende Liste vom Typ List + */ + public void concat(List pList) { + if (pList != this && pList != null && !pList.isEmpty()) { // Nichts tun, + // wenn pList und this identisch, pList leer oder nicht existent. + + if (this.isEmpty()) { // Fall: An leere Liste anfuegen. + this.first = pList.first; + this.last = pList.last; + } else { // Fall: An nicht-leere Liste anfuegen. + this.last.setNextNode(pList.first); + this.last = pList.last; + } + + // Liste pList loeschen. + pList.first = null; + pList.last = null; + pList.current = null; + } + } + + /** + * Wenn die Liste leer ist oder es kein aktuelles Objekt gibt (hasAccess() + * == false), geschieht nichts.
+ * Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das + * aktuelle Objekt geloescht und das Objekt hinter dem geloeschten Objekt + * wird zum aktuellen Objekt.
+ * Wird das Objekt, das am Ende der Liste steht, geloescht, gibt es kein + * aktuelles Objekt mehr. + */ + public void remove() { + // Nichts tun, wenn es kein aktuelle Element gibt oder die Liste leer ist. + if (this.hasAccess() && !this.isEmpty()) { + + if (current == first) { + first = first.getNextNode(); + } else { + ListNode previous = this.getPrevious(current); + if (current == last) { + last = previous; + } + previous.setNextNode(current.getNextNode()); + } + + ListNode temp = current.getNextNode(); + current.setContentObject(null); + current.setNextNode(null); + current = temp; + + //Beim loeschen des letzten Elements last auf null setzen. + if (this.isEmpty()) { + last = null; + } + } + } + + /** + * Liefert den Vorgaengerknoten des Knotens pNode. Ist die Liste leer, pNode + * == null, pNode nicht in der Liste oder pNode der erste Knoten der Liste, + * wird null zurueckgegeben. + * + * @param pNode + * der Knoten, dessen Vorgaenger zurueckgegeben werden soll + * @return der Vorgaenger des Knotens pNode oder null, falls die Liste leer ist, + * pNode == null ist, pNode nicht in der Liste ist oder pNode der erste Knoten + * der Liste ist + */ + private ListNode getPrevious(ListNode pNode) { + if (pNode != null && pNode != first && !this.isEmpty()) { + ListNode temp = first; + while (temp != null && temp.getNextNode() != pNode) { + temp = temp.getNextNode(); + } + return temp; + } else { + return null; + } + } + +} diff --git a/Tiefensuche.java b/Tiefensuche.java new file mode 100644 index 0000000..b549a71 --- /dev/null +++ b/Tiefensuche.java @@ -0,0 +1,84 @@ + +/** + * Implementierung der Tiefensuche auf einem ungereichteten, + * gewichteten Graphen. + */ +public class Tiefensuche { + + private Graph g; + + public Tiefensuche() { + g = new Graph(); + + // Aufbau des Graphen + // Erstellen der Knoten (Vertices) + g.addVertex(new Vertex("Köln")); + g.addVertex(new Vertex("Düsseldorf")); + g.addVertex(new Vertex("Dortmund")); + + Vertex bi = new Vertex("Bielefeld"); + g.addVertex(bi); + Vertex hnv = new Vertex("Hannover"); + g.addVertex(hnv); + Vertex bo = new Vertex("Bochum"); + g.addVertex(bo); + + // Erstellen der Kanten (Edges) + g.addEdge(new Edge( + g.getVertex("Köln"), + g.getVertex("Dortmund"), + 96.0 + )); + g.addEdge(new Edge( + g.getVertex("Düsseldorf"), + g.getVertex("Dortmund"), + 70.0 + )); + g.addEdge(new Edge(g.getVertex("Dortmund"), bo, 22.0)); + g.addEdge(new Edge(bi, hnv, 113.0)); + Edge bi_do = new Edge(bi, g.getVertex("Dortmund"), 112.0); + g.addEdge(bi_do); + Edge bi_dus = new Edge(bi, g.getVertex("Düsseldorf"), 178.0); + g.addEdge(bi_dus); + Edge bo_dus = new Edge(bo, g.getVertex("Düsseldorf"), 52.0); + } + + /** + * Suche nach einem Vertex mit der angegebenen ID mittels der Tiefensuche. + * @param pVertexID + * @return + */ + public boolean findVertex( String pVertexID ) { + g.setAllVertexMarks(false); // Markierungen zurücksetzen + return findVertex(pVertexID, g.getVertices().getContent()); + } + + /** + * Hilfsmethode für die rekursive Tiefensuche. + * Sucht nach einem Vertex mit der angegebenen ID mittels der Tiefensuche, + * ausgehend vom angegebenen Startknoten. + * @param pVertexID + * @return + */ + private boolean findVertex( String pVertexID, Vertex pCurrent ) { + if( pCurrent.getID().equals(pVertexID) ) { + return true; + } else { + pCurrent.setMark(true); + + List neighbours = g.getNeighbours(pCurrent); + neighbours.toFirst(); + while( neighbours.hasAccess() ) { + Vertex v = neighbours.getContent(); + if( !v.isMarked() ) { + if( findVertex(pVertexID, v) ) { + return true; + } + } + neighbours.next(); + } + } + return false; + } + +} diff --git a/TiefensucheTest.java b/TiefensucheTest.java new file mode 100644 index 0000000..37c4067 --- /dev/null +++ b/TiefensucheTest.java @@ -0,0 +1,25 @@ +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class TiefensucheTest { + + @Before + public void setUp() { + + } + + @Test + public void testFindVertex() { + Tiefensuche ts = new Tiefensuche(); + + assertTrue("Der Knoten Köln ist im Graphen vorhanden.", ts.findVertex("Köln")); + assertTrue("Der Knoten Bielefeld ist im Graphen vorhanden.", ts.findVertex("Bielefeld")); + assertTrue("Der Knoten Bochum ist im Graphen vorhanden.", ts.findVertex("Bochum")); + + assertFalse("Der Knoten Tokio ist nicht im Graphen vorhanden.", ts.findVertex("Tokio")); + assertFalse("Der Knoten London ist nicht im Graphen vorhanden.", ts.findVertex("London")); + } + +} diff --git a/Vertex.java b/Vertex.java new file mode 100755 index 0000000..403a08e --- /dev/null +++ b/Vertex.java @@ -0,0 +1,51 @@ +/** + *

+ * Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018 + *

+ *

+ * Klasse Vertex + *

+ *

+ * Die Klasse Vertex stellt einen einzelnen Knoten eines Graphen dar. Jedes Objekt + * dieser Klasse verfuegt ueber eine im Graphen eindeutige ID als String und kann diese + * ID zurueckliefern. Darueber hinaus kann eine Markierung gesetzt und abgefragt werden. + *

+ * + * @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule + * @version Oktober 2015 + */ +public class Vertex{ + //Einmalige ID des Knotens und Markierung + private String id; + private boolean mark; + + /** + * Ein neues Objekt vom Typ Vertex wird erstellt. Seine Markierung hat den Wert false. + */ + public Vertex(String pID){ + id = pID; + mark = false; + } + + /** + * Die Anfrage liefert die ID des Knotens als String. + */ + public String getID(){ + return new String(id); + } + + /** + * Der Auftrag setzt die Markierung des Knotens auf den Wert pMark. + */ + public void setMark(boolean pMark){ + mark = pMark; + } + + /** + * Die Anfrage liefert true, wenn die Markierung des Knotens den Wert true hat, ansonsten false. + */ + public boolean isMarked(){ + return mark; + } + +} diff --git a/package.bluej b/package.bluej new file mode 100644 index 0000000..677f390 --- /dev/null +++ b/package.bluej @@ -0,0 +1,59 @@ +#BlueJ package file +dependency1.from=BinarySearchTree +dependency1.to=ComparableContent +dependency1.type=UsesDependency +dependency2.from=Racingsimulator +dependency2.to=Athlete +dependency2.type=UsesDependency +editor.fx.0.height=738 +editor.fx.0.width=816 +editor.fx.0.x=466 +editor.fx.0.y=146 +objectbench.height=100 +objectbench.width=1256 +package.divider.horizontal=0.6 +package.divider.vertical=0.881243063263041 +package.editor.height=787 +package.editor.width=1145 +package.editor.x=0 +package.editor.y=0 +package.frame.height=1000 +package.frame.width=1296 +package.numDependencies=2 +package.numTargets=4 +package.showExtends=true +package.showUses=true +project.charset=UTF-8 +readme.height=58 +readme.name=@README +readme.width=47 +readme.x=10 +readme.y=10 +target1.height=50 +target1.name=Racingsimulator +target1.showInterface=false +target1.type=ClassTarget +target1.width=130 +target1.x=450 +target1.y=472 +target2.height=50 +target2.name=ComparableContent +target2.showInterface=false +target2.type=InterfaceTarget +target2.width=250 +target2.x=160 +target2.y=270 +target3.height=50 +target3.name=Athlete +target3.showInterface=false +target3.type=ClassTarget +target3.width=90 +target3.x=280 +target3.y=550 +target4.height=50 +target4.name=BinarySearchTree +target4.showInterface=false +target4.type=ClassTarget +target4.width=230 +target4.x=370 +target4.y=90