This commit is contained in:
Asecave
2020-12-05 12:23:51 +01:00
parent 341f1fad94
commit d2cd58e2c3
4 changed files with 254 additions and 223 deletions

View File

@@ -46,4 +46,9 @@ public class Athlete implements ComparableContent<Athlete> {
public boolean isLess(Athlete athlete) { public boolean isLess(Athlete athlete) {
return getFinalTime() < athlete.getFinalTime(); return getFinalTime() < athlete.getFinalTime();
} }
@Override
public String toString() {
return name;
}
} }

View File

@@ -29,236 +29,246 @@
*/ */
public class BinarySearchTree<ContentType extends ComparableContent<ContentType>> { public class BinarySearchTree<ContentType extends ComparableContent<ContentType>> {
/* --------- Anfang der privaten inneren Klasse -------------- */ /* --------- Anfang der privaten inneren Klasse -------------- */
/** /**
* Durch diese innere Klasse kann man dafuer sorgen, dass ein leerer Baum * 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 * null ist, ein nicht-leerer Baum jedoch immer eine nicht-null-Wurzel sowie
* nicht-null-Teilbaeume hat. * nicht-null-Teilbaeume hat.
*/ */
private class BSTNode<CT extends ComparableContent<CT>> { private class BSTNode<CT extends ComparableContent<CT>> {
private CT content; private CT content;
private BinarySearchTree<CT> left, right; private BinarySearchTree<CT> left, right;
public BSTNode(CT pContent) { public BSTNode(CT pContent) {
// Der Knoten hat einen linken und rechten Teilbaum, die // Der Knoten hat einen linken und rechten Teilbaum, die
// beide von null verschieden sind. Also hat ein Blatt immer zwei // beide von null verschieden sind. Also hat ein Blatt immer zwei
// leere Teilbaeume unter sich. // leere Teilbaeume unter sich.
this.content = pContent; this.content = pContent;
left = new BinarySearchTree<CT>(); left = new BinarySearchTree<CT>();
right = new BinarySearchTree<CT>(); right = new BinarySearchTree<CT>();
} }
} }
/* ----------- Ende der privaten inneren Klasse -------------- */ /* ----------- Ende der privaten inneren Klasse -------------- */
private BSTNode<ContentType> node; private BSTNode<ContentType> node;
/** /**
* Der Konstruktor erzeugt einen leeren Suchbaum. * Der Konstruktor erzeugt einen leeren Suchbaum.
*/ */
public BinarySearchTree() { public BinarySearchTree() {
this.node = null; this.node = null;
} }
/** /**
* Diese Anfrage liefert den Wahrheitswert true, wenn der Suchbaum leer ist, * Diese Anfrage liefert den Wahrheitswert true, wenn der Suchbaum leer ist,
* sonst liefert sie den Wert false. * sonst liefert sie den Wert false.
* *
* @return true, wenn der binaere Suchbaum leer ist, sonst false * @return true, wenn der binaere Suchbaum leer ist, sonst false
* *
*/ */
public boolean isEmpty() { public boolean isEmpty() {
return this.node == null; return this.node == null;
} }
/** /**
* Falls der Parameter null ist, geschieht nichts.<br /> * Falls der Parameter null ist, geschieht nichts.<br />
* Falls ein bezueglich der verwendeten Vergleichsmethode isEqual mit * Falls ein bezueglich der verwendeten Vergleichsmethode isEqual mit
* pContent uebereinstimmendes Objekt im geordneten binaeren Suchbau * pContent uebereinstimmendes Objekt im geordneten binaeren Suchbau
* enthalten ist, passiert nichts. <br /> * enthalten ist, passiert nichts. <br />
* Achtung: hier wird davon ausgegangen, dass isEqual genau dann true * Achtung: hier wird davon ausgegangen, dass isEqual genau dann true
* liefert, wenn isLess und isGreater false liefern. <br /> * liefert, wenn isLess und isGreater false liefern. <br />
* Andernfalls (isLess oder isGreater) wird das Objekt pContent entsprechend * Andernfalls (isLess oder isGreater) wird das Objekt pContent entsprechend
* der vorgegebenen Ordnungsrelation in den BinarySearchTree eingeordnet. * der vorgegebenen Ordnungsrelation in den BinarySearchTree eingeordnet.
* *
* @param pContent * @param pContent
* einzufuegendes Objekt vom Typ ContentType * einzufuegendes Objekt vom Typ ContentType
* *
*/ */
public void insert(ContentType pContent) { public void insert(ContentType pContent) {
if (pContent != null) { if (pContent != null) {
if (isEmpty()) { if (isEmpty()) {
this.node = new BSTNode<ContentType>(pContent); this.node = new BSTNode<ContentType>(pContent);
} else if (pContent.isLess(this.node.content)) { } else if (pContent.isLess(this.node.content)) {
this.node.left.insert(pContent); this.node.left.insert(pContent);
} else if(pContent.isGreater(this.node.content)) { } else if(pContent.isGreater(this.node.content)) {
this.node.right.insert(pContent); this.node.right.insert(pContent);
} }
} }
} }
/** /**
* Diese Anfrage liefert den linken Teilbaum des binaeren Suchbaumes. <br /> * Diese Anfrage liefert den linken Teilbaum des binaeren Suchbaumes. <br />
* Wenn er leer ist, wird null zurueckgegeben. * Wenn er leer ist, wird null zurueckgegeben.
* *
* @return den linken Teilbaum (Objekt vom Typ BinarySearchTree<ContentType>) * @return den linken Teilbaum (Objekt vom Typ BinarySearchTree<ContentType>)
* bzw. null, wenn der Suchbaum leer ist * bzw. null, wenn der Suchbaum leer ist
* *
*/ */
public BinarySearchTree<ContentType> getLeftTree() { public BinarySearchTree<ContentType> getLeftTree() {
if (this.isEmpty()) { if (this.isEmpty()) {
return null; return null;
} else { } else {
return this.node.left; return this.node.left;
} }
} }
/** /**
* Diese Anfrage liefert das Inhaltsobjekt des Suchbaumes. Wenn der Suchbaum * Diese Anfrage liefert das Inhaltsobjekt des Suchbaumes. Wenn der Suchbaum
* leer ist, wird null zurueckgegeben. * leer ist, wird null zurueckgegeben.
* *
* @return das Inhaltsobjekt vom Typ ContentType bzw. null, wenn der aktuelle * @return das Inhaltsobjekt vom Typ ContentType bzw. null, wenn der aktuelle
* Suchbaum leer ist * Suchbaum leer ist
* *
*/ */
public ContentType getContent() { public ContentType getContent() {
if (this.isEmpty()) { if (this.isEmpty()) {
return null; return null;
} else { } else {
return this.node.content; return this.node.content;
} }
} }
/** /**
* Diese Anfrage liefert den rechten Teilbaum des binaeren Suchbaumes. <br /> * Diese Anfrage liefert den rechten Teilbaum des binaeren Suchbaumes. <br />
* Wenn er leer ist, wird null zurueckgegeben. * Wenn er leer ist, wird null zurueckgegeben.
* *
* @return den rechten Teilbaum (Objekt vom Typ BinarySearchTree<ContentType>) * @return den rechten Teilbaum (Objekt vom Typ BinarySearchTree<ContentType>)
* bzw. null, wenn der aktuelle Suchbaum leer ist * bzw. null, wenn der aktuelle Suchbaum leer ist
* *
*/ */
public BinarySearchTree<ContentType> getRightTree() { public BinarySearchTree<ContentType> getRightTree() {
if (this.isEmpty()) { if (this.isEmpty()) {
return null; return null;
} else { } else {
return this.node.right; return this.node.right;
} }
} }
/** /**
* Falls ein bezueglich der verwendeten Vergleichsmethode mit * Falls ein bezueglich der verwendeten Vergleichsmethode mit
* pContent uebereinstimmendes Objekt im binaeren Suchbaum enthalten * pContent uebereinstimmendes Objekt im binaeren Suchbaum enthalten
* ist, wird dieses entfernt. Falls der Parameter null ist, aendert sich * ist, wird dieses entfernt. Falls der Parameter null ist, aendert sich
* nichts. * nichts.
* *
* @param pContent * @param pContent
* zu entfernendes Objekt vom Typ ContentType * zu entfernendes Objekt vom Typ ContentType
* *
*/ */
public void remove(ContentType pContent) { public void remove(ContentType pContent) {
if (isEmpty() || pContent == null ) { if (isEmpty() || pContent == null ) {
// Abbrechen, da kein Element zum entfernen vorhanden ist. // Abbrechen, da kein Element zum entfernen vorhanden ist.
return; return;
} }
if (pContent.isLess(node.content)) { if (pContent.isLess(node.content)) {
// Element ist im linken Teilbaum zu loeschen. // Element ist im linken Teilbaum zu loeschen.
node.left.remove(pContent); node.left.remove(pContent);
} else if (pContent.isGreater(node.content)) { } else if (pContent.isGreater(node.content)) {
// Element ist im rechten Teilbaum zu loeschen. // Element ist im rechten Teilbaum zu loeschen.
node.right.remove(pContent); node.right.remove(pContent);
} else { } else {
// Element ist gefunden. // Element ist gefunden.
if (node.left.isEmpty()) { if (node.left.isEmpty()) {
if (node.right.isEmpty()) { if (node.right.isEmpty()) {
// Es gibt keinen Nachfolger. // Es gibt keinen Nachfolger.
node = null; node = null;
} else { } else {
// Es gibt nur rechts einen Nachfolger. // Es gibt nur rechts einen Nachfolger.
node = getNodeOfRightSuccessor(); node = getNodeOfRightSuccessor();
} }
} else if (node.right.isEmpty()) { } else if (node.right.isEmpty()) {
// Es gibt nur links einen Nachfolger. // Es gibt nur links einen Nachfolger.
node = getNodeOfLeftSuccessor(); node = getNodeOfLeftSuccessor();
} else { } else {
// Es gibt links und rechts einen Nachfolger. // Es gibt links und rechts einen Nachfolger.
if (getNodeOfRightSuccessor().left.isEmpty()) { if (getNodeOfRightSuccessor().left.isEmpty()) {
// Der rechte Nachfolger hat keinen linken Nachfolger. // Der rechte Nachfolger hat keinen linken Nachfolger.
node.content = getNodeOfRightSuccessor().content; node.content = getNodeOfRightSuccessor().content;
node.right = getNodeOfRightSuccessor().right; node.right = getNodeOfRightSuccessor().right;
} else { } else {
BinarySearchTree<ContentType> previous = node.right BinarySearchTree<ContentType> previous = node.right
.ancestorOfSmallRight(); .ancestorOfSmallRight();
BinarySearchTree<ContentType> smallest = previous.node.left; BinarySearchTree<ContentType> smallest = previous.node.left;
this.node.content = smallest.node.content; this.node.content = smallest.node.content;
previous.remove(smallest.node.content); previous.remove(smallest.node.content);
} }
} }
} }
} }
/** /**
* Falls ein bezueglich der verwendeten Vergleichsmethode isEqual mit * Falls ein bezueglich der verwendeten Vergleichsmethode isEqual mit
* pContent uebereinstimmendes Objekt im binaeren Suchbaum enthalten ist, * pContent uebereinstimmendes Objekt im binaeren Suchbaum enthalten ist,
* liefert die Anfrage dieses, ansonsten wird null zurueckgegeben. <br /> * liefert die Anfrage dieses, ansonsten wird null zurueckgegeben. <br />
* Falls der Parameter null ist, wird null zurueckgegeben. * Falls der Parameter null ist, wird null zurueckgegeben.
* *
* @param pContent * @param pContent
* zu suchendes Objekt vom Typ ContentType * zu suchendes Objekt vom Typ ContentType
* @return das gefundene Objekt vom Typ ContentType, bei erfolgloser Suche null * @return das gefundene Objekt vom Typ ContentType, bei erfolgloser Suche null
* *
*/ */
public ContentType search(ContentType pContent) { public ContentType search(ContentType pContent) {
if (this.isEmpty() || pContent == null) { if (this.isEmpty() || pContent == null) {
// Abbrechen, da es kein Element zu suchen gibt. // Abbrechen, da es kein Element zu suchen gibt.
return null; return null;
} else { } else {
ContentType content = this.getContent(); ContentType content = this.getContent();
if (pContent.isLess(content)) { if (pContent.isLess(content)) {
// Element wird im linken Teilbaum gesucht. // Element wird im linken Teilbaum gesucht.
return this.getLeftTree().search(pContent); return this.getLeftTree().search(pContent);
} else if (pContent.isGreater(content)) { } else if (pContent.isGreater(content)) {
// Element wird im rechten Teilbaum gesucht. // Element wird im rechten Teilbaum gesucht.
return this.getRightTree().search(pContent); return this.getRightTree().search(pContent);
} else if (pContent.isEqual(content)) { } else if (pContent.isEqual(content)) {
// Element wurde gefunden. // Element wurde gefunden.
return content; return content;
} else { } else {
// Dieser Fall sollte nicht auftreten. // Dieser Fall sollte nicht auftreten.
return null; return null;
} }
} }
} }
/* ----------- Weitere private Methoden -------------- */ /* ----------- Weitere private Methoden -------------- */
/** /**
* Die Methode liefert denjenigen Baum, dessen linker Nachfolger keinen linken * Die Methode liefert denjenigen Baum, dessen linker Nachfolger keinen linken
* Nachfolger mehr hat. Es ist also spaeter moeglich, in einem Baum im * Nachfolger mehr hat. Es ist also spaeter moeglich, in einem Baum im
* rechten Nachfolger den Vorgaenger des linkesten Nachfolgers zu finden. * rechten Nachfolger den Vorgaenger des linkesten Nachfolgers zu finden.
* *
*/ */
private BinarySearchTree<ContentType> ancestorOfSmallRight() { private BinarySearchTree<ContentType> ancestorOfSmallRight() {
if (getNodeOfLeftSuccessor().left.isEmpty()) { if (getNodeOfLeftSuccessor().left.isEmpty()) {
return this; return this;
} else { } else {
return node.left.ancestorOfSmallRight(); return node.left.ancestorOfSmallRight();
} }
} }
private BSTNode<ContentType> getNodeOfLeftSuccessor() { private BSTNode<ContentType> getNodeOfLeftSuccessor() {
return node.left.node; return node.left.node;
} }
private BSTNode<ContentType> getNodeOfRightSuccessor() { private BSTNode<ContentType> getNodeOfRightSuccessor() {
return node.right.node; return node.right.node;
} }
public void printInOrder() { public List<ContentType> getInOrder() {
//TODO List<ContentType> inOrder = new List<>();
} getPartTree(this, inOrder);
return inOrder;
}
private void getPartTree(BinarySearchTree<ContentType> tree, List<ContentType> inOrder) {
if (tree != null && tree.getContent() != null) {
getPartTree(tree.getLeftTree(), inOrder);
inOrder.append(tree.getContent());
getPartTree(tree.getRightTree(), inOrder);
}
}
} }

View File

@@ -22,13 +22,24 @@ public class Competition {
leaderboard.insert(runners.getContent()); leaderboard.insert(runners.getContent());
runners.next(); runners.next();
} }
leaderboard.printInOrder();
} }
public Athlete[] top3() { public Athlete[] top3() {
Athlete[] top = new Athlete[3]; Athlete[] top = new Athlete[3];
//TODO List<Athlete> inOrder = leaderboard.getInOrder();
inOrder.toFirst();
top[0] = inOrder.getContent();
inOrder.next();
if (!inOrder.hasAccess()){
return top;
}
top[1] = inOrder.getContent();
inOrder.next();
if (!inOrder.hasAccess()){
return top;
}
top[2] = inOrder.getContent();
inOrder.next();
return top; return top;
} }
} }

View File

@@ -18,6 +18,11 @@ public class TestCompetition {
competition.newRunner("a"); competition.newRunner("a");
competition.simulate(); competition.simulate();
Athlete[] top = competition.top3();
for (int i = 0; i < top.length; i++) {
System.out.println(top[i] + ": " + top[i].getFinalTime());
}
} }
} }