Initial commit

This commit is contained in:
ngb
2021-01-26 14:18:11 +01:00
commit 1a1d1409f5
7 changed files with 1129 additions and 0 deletions

26
.gitignore vendored Normal file
View File

@@ -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*

235
Dijkstra.java Normal file
View File

@@ -0,0 +1,235 @@
public class Dijkstra {
private Graph graph;
private boolean verbose;
/**
* Implementierung des Dijkstra-Algorithmus auf ungerichteten,
* gewichteten Grapen.
*/
public Dijkstra() {
graph = new Graph();
verbose = false;
}
/**
* Schaltet die ausführliche Ausgabe ein bzw. aus.
*/
public void toggleVerbose() {
verbose = !verbose;
}
/**
* Erstellt einen Testgraphen und führt den Algorithmus für die Strecke
* Münster -> Lünen aus.
*/
public void test() {
System.out.println("Creating graph..");
createGraphExample1();
System.out.println("Searching for shortest path..");
List<Vertex> path = findShortestPath("Münster", "Lünen");
//List<Vertex> path = findShortestPath("Haltern", "Münster");
System.out.println();
System.out.println("Result:");
printPath(path);
}
/**
* Führt den Dijkstra-Algorithmus von einem Startknoten aus und bricht ab,
* sobald der kürzeste Weg zum Zielknoten gefunden wurde.
*
* Der kürzeste Weg wird als Liste von Knoten zurückgegeben. Der kürzeste
* Weg zu den Knoten (auf dem Weg) wird im Attribut {@link Vertex#getValue() value}
* der Knoten gespeichert.
*
* @param from Startknoten
* @param to Endknoten
*/
public List<Vertex> findShortestPath( String from, String to ) {
Vertex start = graph.getVertex(from);
Vertex end = graph.getVertex(to);
// Markierungen zeigen an, ob ein Knoten schon in die
// Liste einsortiert wurde
graph.setAllEdgeMarks(false);
List<Vertex> vList = new List<>();
// Startknoten kommt als Erster in der Liste,
// mit Weglänge 0.0
start.setValue(0.0);
start.setMark(true);
vList.append(start);
while( !vList.isEmpty() ) {
Vertex current = findMinVertex(vList);
if( verbose )
System.out.println("Current node: " + current.getID());
if( current.equals(end) ) {
// Kürzester Weg für den Zielknoten gefunden
// Können abbrechen
if( verbose )
System.out.println(" Vertex found; breaking loop");
break;
}
List<Vertex> neighbours = graph.getNeighbours(current);
neighbours.toFirst();
while( neighbours.hasAccess() ) {
Vertex v = neighbours.getContent();
Edge e = graph.getEdge(current, v);
if( verbose )
System.out.println(" Checking neighbour: " + v.getID());
if( current.getValue() + e.getWeight() < v.getValue() ) {
// Es wurde ein kürzerer Weg gefunden
// Der Knoten wird aktualisiert
if( verbose ) {
if (v.getValue() == Integer.MAX_VALUE) {
System.out.printf(" Shorter path found: %.2f < Infinity\n", current.getValue() + e.getWeight(), v.getValue());
} else {
System.out.printf(" Shorter path found: %.2f < %.2f\n", current.getValue() + e.getWeight(), v.getValue());
}
}
v.setValue(current.getValue() + e.getWeight());
v.setPredecessor(current);
} else {
// Kein kürzerer Weg gefunden
if( verbose )
System.out.printf(" No update: %.2f <= %.2f\n", v.getValue(), current.getValue() + e.getWeight());
}
if( !v.isMarked() ) {
// Der Knoten muss noch in die Liste einsortiert werden.
v.setMark(true);
vList.append(v);
if( verbose )
System.out.println(" Added node to list.");
}
neighbours.next();
}
}
return generatePath(end);
}
/**
* Sucht den Vertex mit dem geringsten Wert aus der Liste, entfernt ihn
* und gibt den Vertex zurück.
* @param pList
* @return
*/
private Vertex findMinVertex( List<Vertex> pList ) {
// Knoten mit kleinstem Wert suchen
pList.toFirst();
Vertex min = pList.getContent();
pList.next();
while( pList.hasAccess() ) {
if (pList.getContent().getValue() < min.getValue() ) {
min = pList.getContent();
}
pList.next();
}
// Knoten wieder suchen und entfernen
pList.toFirst();
while( !pList.getContent().equals(min) ) {
pList.next();
}
pList.remove();
// Fertig
return min;
}
/**
* Erzeugt <strong>nach</strong> Ablauf des Algorithmus den Weg zu einem
* Knoten aus den {@link Vertex#getPredecessor() predecessor} Attributen
* der Knoten.
*
* @param pVertex
* @return
*/
public List<Vertex> generatePath( Vertex pVertex ) {
List<Vertex> shortestpath = new List<>();
double length = 0.0;
Vertex current = pVertex;
while( current != null ) {
shortestpath.insert(current);
shortestpath.toFirst();
current = current.getPredecessor();
}
return shortestpath;
}
/**
* Gibt einen Pfad aus, der in Form einer Liste von Knoten vorliegt. Es
* wird davon ausgegangen, dass die Knoten einen zusammenhängenden Pfad
* darstellen. Ob jeweils Kanten zwischen den Folgeknoten vorliegen wird
* nicht geprüft.
* @param pPath
*/
public void printPath( List<Vertex> pPath ) {
double length = 0.0;
pPath.toFirst();
while(pPath.hasAccess()) {
System.out.println("- " + pPath.getContent().getID());
length = pPath.getContent().getValue();
pPath.next();
}
System.out.printf("Length of shortest path: %.2f\n", length);
}
public void createGraphExample1() {
graph = new Graph();
String[] ids = new String[]{
"Münster", "Hamm", "Dülmen",
"Haltern", "Lüdinghsn", "Werne", "Lünen", "Kamen",
"y", "x", "3", "79", "80"
};
Vertex[] v = new Vertex[ids.length];
for( int i = 0; i < ids.length; i++ ) {
v[i] = new Vertex(ids[i]);
graph.addVertex(v[i]);
}
graph.addEdge(new Edge(v[0], v[1], 40.0));
graph.addEdge(new Edge(v[0], v[11], 24.0));
graph.addEdge(new Edge(v[0], v[5], 37.0));
graph.addEdge(new Edge(v[0], v[9], 8.0));
graph.addEdge(new Edge(v[0], v[8], 13.0));
graph.addEdge(new Edge(v[1], v[7], 17.0));
graph.addEdge(new Edge(v[1], v[6], 24.0));
graph.addEdge(new Edge(v[1], v[11], 24.0));
graph.addEdge(new Edge(v[2], v[8], 31.0));
graph.addEdge(new Edge(v[2], v[3], 12.0));
graph.addEdge(new Edge(v[3], v[4], 20.0));
graph.addEdge(new Edge(v[4], v[10], 16.0));
graph.addEdge(new Edge(v[4], v[11], 15.0));
graph.addEdge(new Edge(v[4], v[6], 21.0));
graph.addEdge(new Edge(v[5], v[12], 5.0));
graph.addEdge(new Edge(v[5], v[6], 10.0));
graph.addEdge(new Edge(v[6], v[8], 12.0));
graph.addEdge(new Edge(v[8], v[10], 1.0));
graph.addEdge(new Edge(v[9], v[10], 4.0));
graph.addEdge(new Edge(v[9], v[11], 15.0));
graph.addEdge(new Edge(v[11], v[12], 11.0));
}
}

75
Edge.java Normal file
View File

@@ -0,0 +1,75 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Klasse Edge
* </p>
* <p>
* 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.
* </p>
*
* @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;
}
}

312
Graph.java Normal file
View File

@@ -0,0 +1,312 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Klasse Graph
* </p>
* <p>
* 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.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version Oktober 2015
*/
public class Graph{
private List<Vertex> vertices;
private List<Edge> 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<Vertex>();
edges = new List<Edge>();
}
/**
* Die Anfrage liefert eine neue Liste aller Knotenobjekte vom Typ List<Vertex>.
*/
public List<Vertex> getVertices(){
//Eine neue Liste mit allen Vertex-Objekten erstellen.
List<Vertex> result = new List<Vertex>();
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<Edge>.
*/
public List<Edge> getEdges(){
//Eine neue Liste mit allen Edge-Objekten erstellen.
List<Edge> result = new List<Edge>();
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<Vertex>. 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<Vertex> getNeighbours(Vertex pVertex){
List<Vertex> result = new List<Vertex>();
//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<Edge> getEdges(Vertex pVertex){
List<Edge> result = new List<Edge>();
//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();
}
}

345
List.java Normal file
View File

@@ -0,0 +1,345 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Generische Klasse List<ContentType>
* </p>
* <p>
* Objekt der generischen Klasse List verwalten beliebig viele linear
* angeordnete Objekte vom Typ ContentType. Auf hoechstens ein Listenobjekt,
* aktuellesObjekt genannt, kann jeweils zugegriffen werden.<br />
* Wenn eine Liste leer ist, vollstaendig durchlaufen wurde oder das aktuelle
* Objekt am Ende der Liste geloescht wurde, gibt es kein aktuelles Objekt.<br />
* 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. <br />
* Das aktuelle Objekt kann gelesen, veraendert oder geloescht werden. Ausserdem
* kann vor dem aktuellen Objekt ein Listenobjekt eingefuegt werden.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version Generisch_06 2015-10-25
*/
public class List<ContentType> {
/* --------- 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. <br />
* Wenn die Liste leer ist, wird pContent in die Liste eingefuegt und es
* gibt weiterhin kein aktuelles Objekt (hasAccess() == false). <br />
* 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.<br />
* Ansonsten wird ein neues Objekt pContent am Ende der Liste eingefuegt.
* Das aktuelle Objekt bleibt unveraendert. <br />
* 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.<br />
* 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<ContentType>
*/
public void concat(List<ContentType> 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.<br />
* Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das
* aktuelle Objekt geloescht und das Objekt hinter dem geloeschten Objekt
* wird zum aktuellen Objekt. <br />
* 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;
}
}
}

77
Vertex.java Normal file
View File

@@ -0,0 +1,77 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Klasse Vertex
* </p>
* <p>
* 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.
* </p>
*
* @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;
// Ergänzugnen für Dijkstra
// Speicher für den kürzesten Weg
private double value;
// Vorgängenknoten im kürzesten Weg
private Vertex predecessor;
/**
* Ein neues Objekt vom Typ Vertex wird erstellt. Seine Markierung hat den Wert false.
*/
public Vertex(String pID){
id = pID;
mark = false;
value = Integer.MAX_VALUE;
predecessor = null;
}
/**
* 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;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public Vertex getPredecessor() {
return predecessor;
}
public void setPredecessor(Vertex predecessor) {
this.predecessor = predecessor;
}
}

59
package.bluej Normal file
View File

@@ -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