added useful files

This commit is contained in:
Tim 2020-12-02 13:06:17 +01:00
parent 7459a582b7
commit 70a5d59d6e
10 changed files with 1734 additions and 0 deletions

345
01 linear/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;
}
}
}

142
01 linear/Queue.java Normal file
View File

@ -0,0 +1,142 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Generische Klasse Queue<ContentType>
* </p>
* <p>
* Objekte der generischen Klasse Queue (Warteschlange) verwalten beliebige
* Objekte vom Typ ContentType nach dem First-In-First-Out-Prinzip, d.h., das
* zuerst abgelegte Objekt wird als erstes wieder entnommen. Alle Methoden haben
* eine konstante Laufzeit, unabhaengig von der Anzahl der verwalteten Objekte.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version Generisch_02 2014-02-21
*/
public class Queue<ContentType> {
/* --------- Anfang der privaten inneren Klasse -------------- */
private class QueueNode {
private ContentType content = null;
private QueueNode nextNode = null;
/**
* Ein neues Objekt vom Typ QueueNode<ContentType> wird erschaffen.
* Der Inhalt wird per Parameter gesetzt. Der Verweis ist leer.
*
* @param pContent das Inhaltselement des Knotens vom Typ ContentType
*/
public QueueNode(ContentType pContent) {
content = pContent;
nextNode = null;
}
/**
* Der Verweis wird auf das Objekt, das als Parameter uebergeben wird,
* gesetzt.
*
* @param pNext der Nachfolger des Knotens
*/
public void setNext(QueueNode pNext) {
nextNode = pNext;
}
/**
* Liefert das naechste Element des aktuellen Knotens.
*
* @return das Objekt vom Typ QueueNode, auf das der aktuelle Verweis zeigt
*/
public QueueNode getNext() {
return nextNode;
}
/**
* Liefert das Inhaltsobjekt des Knotens vom Typ ContentType.
*
* @return das Inhaltsobjekt des Knotens
*/
public ContentType getContent() {
return content;
}
}
/* ----------- Ende der privaten inneren Klasse -------------- */
private QueueNode head;
private QueueNode tail;
/**
* Eine leere Schlange wird erzeugt.
* Objekte, die in dieser Schlange verwaltet werden, muessen vom Typ
* ContentType sein.
*/
public Queue() {
head = null;
tail = null;
}
/**
* Die Anfrage liefert den Wert true, wenn die Schlange keine Objekte enthaelt,
* sonst liefert sie den Wert false.
*
* @return true, falls die Schlange leer ist, sonst false
*/
public boolean isEmpty() {
return head == null;
}
/**
* Das Objekt pContentType wird an die Schlange angehaengt.
* Falls pContentType gleich null ist, bleibt die Schlange unveraendert.
*
* @param pContent
* das anzuhaengende Objekt vom Typ ContentType
*/
public void enqueue(ContentType pContent) {
if (pContent != null) {
QueueNode newNode = new QueueNode(pContent);
if (this.isEmpty()) {
head = newNode;
tail = newNode;
} else {
tail.setNext(newNode);
tail = newNode;
}
}
}
/**
* Das erste Objekt wird aus der Schlange entfernt.
* Falls die Schlange leer ist, wird sie nicht veraendert.
*/
public void dequeue() {
if (!this.isEmpty()) {
head = head.getNext();
if (this.isEmpty()) {
head = null;
tail = null;
}
}
}
/**
* Die Anfrage liefert das erste Objekt der Schlange.
* Die Schlange bleibt unveraendert.
* Falls die Schlange leer ist, wird null zurueckgegeben.
*
* @return das erste Objekt der Schlange vom Typ ContentType oder null,
* falls die Schlange leer ist
*/
public ContentType front() {
if (this.isEmpty()) {
return null;
} else {
return head.getContent();
}
}
}

126
01 linear/Stack.java Normal file
View File

@ -0,0 +1,126 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Generische Klasse Stack<ContentType>
* </p>
* <p>
* Objekte der generischen Klasse Stack (Keller, Stapel) verwalten beliebige
* Objekte vom Typ ContentType nach dem Last-In-First-Out-Prinzip, d.h., das
* zuletzt abgelegte Objekt wird als erstes wieder entnommen. Alle Methoden
* haben eine konstante Laufzeit, unabhaengig von der Anzahl der verwalteten
* Objekte.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version Generisch_02 2014-02-21
*/
public class Stack<ContentType> {
/* --------- Anfang der privaten inneren Klasse -------------- */
private class StackNode {
private ContentType content = null;
private StackNode nextNode = null;
/**
* Ein neues Objekt vom Typ StackNode<ContentType> wird erschaffen. <br />
* Der Inhalt wird per Parameter gesetzt. Der Verweis ist leer.
*
* @param pContent der Inhalt des Knotens
*/
public StackNode(ContentType pContent) {
content = pContent;
nextNode = null;
}
/**
* Der Verweis wird auf das Objekt, das als Parameter uebergeben wird,
* gesetzt.
*
* @param pNext der Nachfolger des Knotens
*/
public void setNext(StackNode pNext) {
nextNode = pNext;
}
/**
*
* @return das Objekt, auf das der aktuelle Verweis zeigt
*/
public StackNode getNext() {
return nextNode;
}
/**
* @return das Inhaltsobjekt vom Typ ContentType
*/
public ContentType getContent() {
return content;
}
}
/* ----------- Ende der privaten inneren Klasse -------------- */
private StackNode head;
/**
* Ein leerer Stapel wird erzeugt. Objekte, die in diesem Stapel verwaltet
* werden, muessen vom Typ ContentType sein.
*/
public Stack() {
head = null;
}
/**
* Die Anfrage liefert den Wert true, wenn der Stapel keine Objekte
* enthaelt, sonst liefert sie den Wert false.
*
* @return true, falls der Stapel leer ist, sonst false
*/
public boolean isEmpty() {
return (head == null);
}
/**
* Das Objekt pContentType wird oben auf den Stapel gelegt. Falls
* pContentType gleich null ist, bleibt der Stapel unveraendert.
*
* @param pContent
* das einzufuegende Objekt vom Typ ContentType
*/
public void push(ContentType pContent) {
if (pContent != null) {
StackNode node = new StackNode(pContent);
node.setNext(head);
head = node;
}
}
/**
* Das zuletzt eingefuegte Objekt wird von dem Stapel entfernt. Falls der
* Stapel leer ist, bleibt er unveraendert.
*/
public void pop() {
if (!isEmpty()) {
head = head.getNext();
}
}
/**
* Die Anfrage liefert das oberste Stapelobjekt. Der Stapel bleibt
* unveraendert. Falls der Stapel leer ist, wird null zurueckgegeben.
*
* @return das oberste Stackelement vom Typ ContentType oder null, falls
* der Stack leer ist
*/
public ContentType top() {
if (!this.isEmpty()) {
return head.getContent();
} else {
return null;
}
}
}

View File

@ -0,0 +1,260 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Generische Klasse BinarySearchTree<ContentType>
* </p>
* <p>
* Mithilfe der generischen Klasse BinarySearchTree koennen beliebig viele
* Objekte in einem Binaerbaum (binaerer Suchbaum) entsprechend einer
* Ordnungsrelation verwaltet werden. <br />
* Ein Objekt der Klasse stellt entweder einen leeren binaeren Suchbaum dar oder
* verwaltet ein Inhaltsobjekt sowie einen linken und einen rechten Teilbaum,
* die ebenfalls Objekte der Klasse BinarySearchTree sind.<br />
* Die Klasse der Objekte, die in dem Suchbaum verwaltet werden sollen, muss
* das generische Interface ComparableContent implementieren. Dabei muss durch
* Ueberschreiben der drei Vergleichsmethoden isLess, isEqual, isGreater (s.
* Dokumentation des Interfaces) eine eindeutige Ordnungsrelation festgelegt
* sein. <br />
* Alle Objekte im linken Teilbaum sind kleiner als das Inhaltsobjekt des
* binaeren Suchbaums. Alle Objekte im rechten Teilbaum sind groesser als das
* Inhaltsobjekt des binaeren Suchbaums. Diese Bedingung gilt (rekursiv) auch in
* beiden Teilbaeumen. <br />
* Hinweis: In dieser Version wird die Klasse BinaryTree nicht benutzt.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version Generisch_03 2017-11-28
*/
public class BinarySearchTree<ContentType extends ComparableContent<ContentType>> {
/* --------- Anfang der privaten inneren Klasse -------------- */
/**
* Durch diese innere Klasse kann man dafuer sorgen, dass ein leerer Baum
* null ist, ein nicht-leerer Baum jedoch immer eine nicht-null-Wurzel sowie
* nicht-null-Teilbaeume hat.
*/
private class BSTNode<CT extends ComparableContent<CT>> {
private CT content;
private BinarySearchTree<CT> left, right;
public BSTNode(CT pContent) {
// Der Knoten hat einen linken und rechten Teilbaum, die
// beide von null verschieden sind. Also hat ein Blatt immer zwei
// leere Teilbaeume unter sich.
this.content = pContent;
left = new BinarySearchTree<CT>();
right = new BinarySearchTree<CT>();
}
}
/* ----------- Ende der privaten inneren Klasse -------------- */
private BSTNode<ContentType> node;
/**
* Der Konstruktor erzeugt einen leeren Suchbaum.
*/
public BinarySearchTree() {
this.node = null;
}
/**
* Diese Anfrage liefert den Wahrheitswert true, wenn der Suchbaum leer ist,
* sonst liefert sie den Wert false.
*
* @return true, wenn der binaere Suchbaum leer ist, sonst false
*
*/
public boolean isEmpty() {
return this.node == null;
}
/**
* Falls der Parameter null ist, geschieht nichts.<br />
* Falls ein bezueglich der verwendeten Vergleichsmethode isEqual mit
* pContent uebereinstimmendes Objekt im geordneten binaeren Suchbau
* enthalten ist, passiert nichts. <br />
* Achtung: hier wird davon ausgegangen, dass isEqual genau dann true
* liefert, wenn isLess und isGreater false liefern. <br />
* Andernfalls (isLess oder isGreater) wird das Objekt pContent entsprechend
* der vorgegebenen Ordnungsrelation in den BinarySearchTree eingeordnet.
*
* @param pContent
* einzufuegendes Objekt vom Typ ContentType
*
*/
public void insert(ContentType pContent) {
if (pContent != null) {
if (isEmpty()) {
this.node = new BSTNode<ContentType>(pContent);
} else if (pContent.isLess(this.node.content)) {
this.node.left.insert(pContent);
} else if(pContent.isGreater(this.node.content)) {
this.node.right.insert(pContent);
}
}
}
/**
* Diese Anfrage liefert den linken Teilbaum des binaeren Suchbaumes. <br />
* Wenn er leer ist, wird null zurueckgegeben.
*
* @return den linken Teilbaum (Objekt vom Typ BinarySearchTree<ContentType>)
* bzw. null, wenn der Suchbaum leer ist
*
*/
public BinarySearchTree<ContentType> getLeftTree() {
if (this.isEmpty()) {
return null;
} else {
return this.node.left;
}
}
/**
* Diese Anfrage liefert das Inhaltsobjekt des Suchbaumes. Wenn der Suchbaum
* leer ist, wird null zurueckgegeben.
*
* @return das Inhaltsobjekt vom Typ ContentType bzw. null, wenn der aktuelle
* Suchbaum leer ist
*
*/
public ContentType getContent() {
if (this.isEmpty()) {
return null;
} else {
return this.node.content;
}
}
/**
* Diese Anfrage liefert den rechten Teilbaum des binaeren Suchbaumes. <br />
* Wenn er leer ist, wird null zurueckgegeben.
*
* @return den rechten Teilbaum (Objekt vom Typ BinarySearchTree<ContentType>)
* bzw. null, wenn der aktuelle Suchbaum leer ist
*
*/
public BinarySearchTree<ContentType> getRightTree() {
if (this.isEmpty()) {
return null;
} else {
return this.node.right;
}
}
/**
* Falls ein bezueglich der verwendeten Vergleichsmethode mit
* pContent uebereinstimmendes Objekt im binaeren Suchbaum enthalten
* ist, wird dieses entfernt. Falls der Parameter null ist, aendert sich
* nichts.
*
* @param pContent
* zu entfernendes Objekt vom Typ ContentType
*
*/
public void remove(ContentType pContent) {
if (isEmpty() || pContent == null ) {
// Abbrechen, da kein Element zum entfernen vorhanden ist.
return;
}
if (pContent.isLess(node.content)) {
// Element ist im linken Teilbaum zu loeschen.
node.left.remove(pContent);
} else if (pContent.isGreater(node.content)) {
// Element ist im rechten Teilbaum zu loeschen.
node.right.remove(pContent);
} else {
// Element ist gefunden.
if (node.left.isEmpty()) {
if (node.right.isEmpty()) {
// Es gibt keinen Nachfolger.
node = null;
} else {
// Es gibt nur rechts einen Nachfolger.
node = getNodeOfRightSuccessor();
}
} else if (node.right.isEmpty()) {
// Es gibt nur links einen Nachfolger.
node = getNodeOfLeftSuccessor();
} else {
// Es gibt links und rechts einen Nachfolger.
if (getNodeOfRightSuccessor().left.isEmpty()) {
// Der rechte Nachfolger hat keinen linken Nachfolger.
node.content = getNodeOfRightSuccessor().content;
node.right = getNodeOfRightSuccessor().right;
} else {
BinarySearchTree<ContentType> previous = node.right
.ancestorOfSmallRight();
BinarySearchTree<ContentType> smallest = previous.node.left;
this.node.content = smallest.node.content;
previous.remove(smallest.node.content);
}
}
}
}
/**
* Falls ein bezueglich der verwendeten Vergleichsmethode isEqual mit
* pContent uebereinstimmendes Objekt im binaeren Suchbaum enthalten ist,
* liefert die Anfrage dieses, ansonsten wird null zurueckgegeben. <br />
* Falls der Parameter null ist, wird null zurueckgegeben.
*
* @param pContent
* zu suchendes Objekt vom Typ ContentType
* @return das gefundene Objekt vom Typ ContentType, bei erfolgloser Suche null
*
*/
public ContentType search(ContentType pContent) {
if (this.isEmpty() || pContent == null) {
// Abbrechen, da es kein Element zu suchen gibt.
return null;
} else {
ContentType content = this.getContent();
if (pContent.isLess(content)) {
// Element wird im linken Teilbaum gesucht.
return this.getLeftTree().search(pContent);
} else if (pContent.isGreater(content)) {
// Element wird im rechten Teilbaum gesucht.
return this.getRightTree().search(pContent);
} else if (pContent.isEqual(content)) {
// Element wurde gefunden.
return content;
} else {
// Dieser Fall sollte nicht auftreten.
return null;
}
}
}
/* ----------- Weitere private Methoden -------------- */
/**
* Die Methode liefert denjenigen Baum, dessen linker Nachfolger keinen linken
* Nachfolger mehr hat. Es ist also spaeter moeglich, in einem Baum im
* rechten Nachfolger den Vorgaenger des linkesten Nachfolgers zu finden.
*
*/
private BinarySearchTree<ContentType> ancestorOfSmallRight() {
if (getNodeOfLeftSuccessor().left.isEmpty()) {
return this;
} else {
return node.left.ancestorOfSmallRight();
}
}
private BSTNode<ContentType> getNodeOfLeftSuccessor() {
return node.left.node;
}
private BSTNode<ContentType> getNodeOfRightSuccessor() {
return node.right.node;
}
}

203
02 baum/BinaryTree.java Normal file
View File

@ -0,0 +1,203 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2017.
* </p>
* <p>
* Generische Klasse BinaryTree<ContentType>
* </p>
* <p>
* Mithilfe der generischen Klasse BinaryTree koennen beliebig viele
* Inhaltsobjekte vom Typ ContentType in einem Binaerbaum verwaltet werden. Ein
* Objekt der Klasse stellt entweder einen leeren Baum dar oder verwaltet ein
* Inhaltsobjekt sowie einen linken und einen rechten Teilbaum, die ebenfalls
* Objekte der generischen Klasse BinaryTree sind.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule;
* Materialien zum schulinternen Lehrplan Informatik SII
* @version Generisch_04 2020-03-11
*/
public class BinaryTree<ContentType> {
/* --------- Anfang der privaten inneren Klasse -------------- */
/**
* Durch diese innere Klasse kann man dafuer sorgen, dass ein leerer Baum null
* ist, ein nicht-leerer Baum jedoch immer eine nicht-null-Wurzel sowie
* nicht-null-Teilbaeume, ggf. leere Teilbaeume hat.
*/
private class BTNode {
private ContentType content;
private BinaryTree<ContentType> left, right;
private BTNode(ContentType pContent) {
// Der Knoten hat einen linken und einen rechten Teilbaum, die
// beide von null verschieden sind. Also hat ein Blatt immer zwei
// leere Teilbaeume unter sich.
this.content = pContent;
left = new BinaryTree<ContentType>();
right = new BinaryTree<ContentType>();
}
}
/* ----------- Ende der privaten inneren Klasse -------------- */
private BTNode node;
/**
* Nach dem Aufruf des Konstruktors existiert ein leerer Binaerbaum.
*/
public BinaryTree() {
this.node = null;
}
/**
* Wenn der Parameter pContent ungleich null ist, existiert nach dem Aufruf des
* Konstruktors der Binaerbaum und hat pContent als Inhaltsobjekt und zwei leere
* Teilbaeume. Falls der Parameter null ist, wird ein leerer Binaerbaum erzeugt.
*
* @param pContent das Inhaltsobjekt des Wurzelknotens vom Typ ContentType
*/
public BinaryTree(ContentType pContent) {
if (pContent != null) {
this.node = new BTNode(pContent);
} else {
this.node = null;
}
}
/**
* Wenn der Parameter pContent ungleich null ist, wird ein Binaerbaum mit
* pContent als Inhalt und den beiden Teilbaeumen pLeftTree und pRightTree
* erzeugt. Sind pLeftTree oder pRightTree gleich null, wird der entsprechende
* Teilbaum als leerer Binaerbaum eingefuegt. So kann es also nie passieren,
* dass linke oder rechte Teilbaeume null sind. Wenn der Parameter pContent
* gleich null ist, wird ein leerer Binaerbaum erzeugt.
*
* @param pContent das Inhaltsobjekt des Wurzelknotens vom Typ ContentType
* @param pLeftTree der linke Teilbaum vom Typ BinaryTree<ContentType>
* @param pRightTree der rechte Teilbaum vom Typ BinaryTree<ContentType>
*/
public BinaryTree(ContentType pContent, BinaryTree<ContentType> pLeftTree, BinaryTree<ContentType> pRightTree) {
if (pContent != null) {
this.node = new BTNode(pContent);
if (pLeftTree != null) {
this.node.left = pLeftTree;
} else {
this.node.left = new BinaryTree<ContentType>();
}
if (pRightTree != null) {
this.node.right = pRightTree;
} else {
this.node.right = new BinaryTree<ContentType>();
}
} else {
// Da der Inhalt null ist, wird ein leerer BinarySearchTree erzeugt.
this.node = null;
}
}
/**
* Diese Anfrage liefert den Wahrheitswert true, wenn der Binaerbaum leer ist,
* sonst liefert sie den Wert false.
*
* @return true, wenn der Binaerbaum leer ist, sonst false
*/
public boolean isEmpty() {
return this.node == null;
}
/**
* Wenn pContent null ist, geschieht nichts. <br />
* Ansonsten: Wenn der Binaerbaum leer ist, wird der Parameter pContent als
* Inhaltsobjekt sowie ein leerer linker und rechter Teilbaum eingefuegt. Ist
* der Binaerbaum nicht leer, wird das Inhaltsobjekt durch pContent ersetzt. Die
* Teilbaeume werden nicht geaendert.
*
* @param pContent neues Inhaltsobjekt vom Typ ContentType
*/
public void setContent(ContentType pContent) {
if (pContent != null) {
if (this.isEmpty()) {
node = new BTNode(pContent);
this.node.left = new BinaryTree<ContentType>();
this.node.right = new BinaryTree<ContentType>();
}
this.node.content = pContent;
}
}
/**
* Diese Anfrage liefert das Inhaltsobjekt des Binaerbaums. Wenn der Binaerbaum
* leer ist, wird null zurueckgegeben.
*
* @return das Inhaltsobjekt der Wurzel vom Typ ContentType bzw. null, wenn der
* Binaerbaum leer ist
*/
public ContentType getContent() {
if (this.isEmpty()) {
return null;
} else {
return this.node.content;
}
}
/**
* Falls der Parameter null ist, geschieht nichts. Wenn der Binaerbaum leer ist,
* wird pTree nicht angehaengt. Andernfalls erhaelt der Binaerbaum den
* uebergebenen BinaryTree als linken Teilbaum.
*
* @param pTree neuer linker Teilbaum vom Typ BinaryTree<ContentType>
*/
public void setLeftTree(BinaryTree<ContentType> pTree) {
if (!this.isEmpty() && pTree != null) {
this.node.left = pTree;
}
}
/**
* Falls der Parameter null ist, geschieht nichts. Wenn der Binaerbaum leer ist,
* wird pTree nicht angehaengt. Andernfalls erhaelt der Binaerbaum den
* uebergebenen BinaryTree als rechten Teilbaum.
*
* @param pTree neuer linker Teilbaum vom Typ BinaryTree<ContentType>
*/
public void setRightTree(BinaryTree<ContentType> pTree) {
if (!this.isEmpty() && pTree != null) {
this.node.right = pTree;
}
}
/**
* Diese Anfrage liefert den linken Teilbaum des Binaerbaumes. Wenn der
* Binaerbaum leer ist, wird null zurueckgegeben.
*
* @return linker Teilbaum vom Typ BinaryTree<ContentType> oder null, wenn der
* aktuelle Binaerbaum leer ist
*/
public BinaryTree<ContentType> getLeftTree() {
if (!this.isEmpty()) {
return this.node.left;
} else {
return null;
}
}
/**
* Diese Anfrage liefert den rechten Teilbaum des Binaerbaumes. Wenn der
* Binaerbaum (this) leer ist, wird null zurueckgegeben.
*
* @return rechter Teilbaum vom Typ BinaryTree<ContentType> oder null, wenn der
* aktuelle Binaerbaum (this) leer ist
*/
public BinaryTree<ContentType> getRightTree() {
if (!this.isEmpty()) {
return this.node.right;
} else {
return null;
}
}
}

View File

@ -0,0 +1,60 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Generisches Interface (Schnittstelle) ComparableContent<ContentType>
* </p>
* <p>
* <p>Das generische Interface ComparableContent<ContentType> legt die Methoden
* fest, ueber die Objekte verfuegen muessen, die in einen binaeren Suchbaum
* (BinarySearchTree) eingefuegt werden sollen. Die Ordnungsrelation wird in
* Klassen, die ComparableContent implementieren durch Ueberschreiben der drei
* implizit abstrakten Methoden isGreater, isEqual und isLess festgelegt.
* </p>
* </p>
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version Generisch_02 2014-03-01
*/
public interface ComparableContent<ContentType> {
/**
* Wenn festgestellt wird, dass das Objekt, von dem die Methode aufgerufen
* wird, bzgl. der gewuenschten Ordnungsrelation groesser als das Objekt
* pContent ist, wird true geliefert. Sonst wird false geliefert.
*
* @param pContent
* das mit dem aufrufenden Objekt zu vergleichende Objekt vom
* Typ ContentType
* @return true, wenn das aufrufende Objekt groesser ist als das Objekt
* pContent, sonst false
*/
public boolean isGreater(ContentType pContent);
/**
* Wenn festgestellt wird, dass das Objekt, von dem die Methode aufgerufen
* wird, bzgl. der gewuenschten Ordnungsrelation gleich gross wie das Objekt
* pContent ist, wird true geliefert. Sonst wird false geliefert.
*
* @param pContent
* das mit dem aufrufenden Objekt zu vergleichende Objekt vom
* Typ ContentType
* @return true, wenn das aufrufende Objekt gleich gross ist wie das Objekt
* pContent, sonst false
*/
public boolean isEqual(ContentType pContent);
/**
* Wenn festgestellt wird, dass das Objekt, von dem die Methode aufgerufen
* wird, bzgl. der gewuenschten Ordnungsrelation kleiner als das Objekt
* pContent ist, wird true geliefert. Sonst wird false geliefert.
*
* @param pContent
* das mit dem aufrufenden Objekt zu vergleichende Objekt vom
* Typ ContentType
* @return true, wenn das aufrufende Objekt kleiner ist als das Objekt
* pContent, sonst false
*/
public boolean isLess(ContentType pContent);
}

75
03 graph/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
03 graph/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;
}