Skip to content

Instantly share code, notes, and snippets.

@vbe0201
Last active January 10, 2020 17:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vbe0201/0ea3af4290b19869714ff6e836684a0f to your computer and use it in GitHub Desktop.
Save vbe0201/0ea3af4290b19869714ff6e836684a0f to your computer and use it in GitHub Desktop.
Implementation einer einfach verketteten Liste in Java.
/**
* Ein Listenelement, welches den Abschluss und damit den
* letzten Knoten einer verketteten Liste darstellt.
*
* @author Valentin B.
* @version 01/10/2020
*/
public class Abschluss<T> implements Listenelement<T> {
public int restlaengeGeben() {
return 0;
}
public Listenelement<T> hintenEinfuegen(T element) {
return new Knoten<T>(this, element);
}
public T elementSuchen(int index) throws IndexOutOfBoundsException {
throw new IndexOutOfBoundsException("Der Index uebersteigt die Anzahl der Elemente in der Liste.");
}
public Abschluss<T> sucheAbschluss() {
return this;
}
}
/**
* Ein Listenelement, was einen gewoehnlichen Knoten
* fuer ein Datenelement in der Liste bildet.
*
* Alle Knoten einer Liste sind miteinander verknuepft,
* indem jeder von ihnen eine Referenz auf das nachfolgende
* @ref Listenelement haelt.
*
* @author Valentin B.
* @version 01/10/2020
*/
public class Knoten<T> implements Listenelement<T> {
/**
* Die Referenz auf das nachfolgende
* @ref Listenelement in der Kette.
*/
private Listenelement<T> nachfolger;
/**
* Das Datenelement, das den Inhalt dieses Knotens
* bildet.
*/
private T inhalt;
/**
* Erzeugt eine neue Instanz von @ref Knoten mit
* dem gegebenen Nachfolger und dem gegebenen Inhalt.
*
* @param nachfolger Der Nachfolger des neuen Knotens.
* @param inhalt Der Inhalt des neuen Knotens.
*/
public Knoten(Listenelement<T> nachfolger, T inhalt) {
this.nachfolger = nachfolger;
this.inhalt = inhalt;
}
/**
* Gibt die Referenz auf den nachfolgenden @ref Knoten
* zurueck.
*
* @return Der Nachfolger dieses Listenelements.
*/
public Listenelement<T> nachfolgerGeben() {
return this.nachfolger;
}
/**
* Setzt einen neuen nachfolgenden @ref Knoten fuer
* dieses Listenelement.
*
* @param nachfolger Der neue Nachfolger.
*/
public void nachfolgerSetzen(Listenelement<T> nachfolger) {
this.nachfolger = nachfolger;
}
/**
* Gibt die Referenz auf den Inhalt dieses @ref Knoten
* zurueck.
*
* @return Der Inhalt.
*/
public T inhaltGeben() {
return this.inhalt;
}
/**
* Setzt einen neuen Inhalt fuer diesen @ref Knoten.
*
* @param inhalt Der neue Inhalt.
*/
public void inhaltSetzen(T inhalt) {
this.inhalt = inhalt;
}
public int restlaengeGeben() {
return nachfolger.restlaengeGeben() + 1;
}
public Listenelement<T> hintenEinfuegen(T element) {
nachfolgerSetzen(nachfolger.hintenEinfuegen(element));
return this;
}
public T elementSuchen(int index) throws IndexOutOfBoundsException {
if (index == 0)
return inhaltGeben();
else
return nachfolger.elementSuchen(index - 1);
}
public Abschluss<T> sucheAbschluss() {
return nachfolger.sucheAbschluss();
}
}
/**
* Implementation einer einfach verkettete Liste.
*
* @author Valentin B.
* @version 01/10/2020
*/
public class Liste<T> {
/**
* Eine Referenz auf den Anfang der Kette.
*/
private Listenelement<T> anfang;
/**
* Erzeugt eine neue Instanz der @ref Liste.
*
* Diese Liste ist nach dem Erzeugen leer.
*/
public Liste() {
anfang = new Abschluss<T>();
}
/**
* Bestimmt die Laenge der Liste.
*
* @return Die Anzahl der @ref Knoten in der Liste.
*/
public int laengeGeben() {
return anfang.restlaengeGeben();
}
/**
* Fuegt ein Element am Anfang der Liste ein.
*
* @param element Das Datenelement.
*
* @note Diese Methode ist nicht rekursiv!
*/
public void vorneEinfuegen(T element) {
anfang = new Knoten<T>(anfang, element);
}
/**
* Fuegt ein Element am Ende der Liste ein.
*
* @param element Das Datenelement.
*/
public void hintenEinfuegen(T element) {
anfang = anfang.hintenEinfuegen(element);
}
/**
* Gibt ein Datenelement an einer bestimmten Position zurueck.
*
* @param index Die Position des Elements innerhalb der Liste.
* @return Das gefundene Datenelement.
*
* @throws IndexOutOfBoundsException Wird geworfen, wenn der
* gegebene Index die Grenzen der Liste ueberschreitet.
*/
public T elementGeben(int index) throws IndexOutOfBoundsException {
if (index < 0)
throw new IndexOutOfBoundsException("Der Index darf nicht negativ sein!");
return anfang.elementSuchen(index);
}
/**
* Loescht alle Elemente aus der Liste.
*/
public void leeren() {
anfang = anfang.sucheAbschluss();
}
}
/**
* Ein allgemeines Interface fuer Listenelemente.
*
* Unter Verwendung des Entwurfsmusters "Kompositum"
* gibt es die Schnittstellen vor, die essentiell
* fuer die Implementierung der rekursiven Struktur
* sind.
*
* @author Valentin B.
* @version 01/10/2020
*/
public interface Listenelement<T> {
/**
* Zaehlt die restlichen Listenelemente, die sich
* in der Liste befinden.
*
* @return Die Restlaenge der Liste.
*/
int restlaengeGeben();
/**
* Fuegt ein neues Datenelement am Ende der Liste ein.
*
* Das dabei resultierende Listenelement ist hier die
* neue "Kette" an Listenelementen, die sich nach dem
* Einfuegen ergibt.
* Jeder @ref Knoten sollte den Rueckgabewert dieser
* Methode von daher als seinen neuen Nachfolger setzen.
*
* @param element Das Datenelement.
* @return Der neue Nachfolger.
*/
Listenelement<T> hintenEinfuegen(T element);
/**
* Sucht ein Datenelement an einer bestimmten Position.
*
* @param index Die vermeintliche Position des Elements.
* @return Das Datenelement, nachdem es gefunden wurde.
*
* @throws IndexOutOfBoundsException Wird geworfen, wenn
* der gegebene Index die Grenzen der Liste ueberschreitet.
*/
T elementSuchen(int index) throws IndexOutOfBoundsException;
/**
* Sucht den @ref Abschluss der Listenelement-Verkettung.
*
* @return Der Abschluss.
*/
Abschluss<T> sucheAbschluss();
}
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Unit Tests fuer die Liste.
*
* @author Valentin B.
* @version 01/10/2020
*/
public class ListeTest {
/**
* Testet primaer die Methoden Liste#vorneEinfuegen und
* Liste#hintenEinfuegen auf Korrektheit.
*/
@Test
public void einfuegenTest() {
Liste<String> liste = new Liste<String>();
liste.hintenEinfuegen("Test1");
liste.hintenEinfuegen("Test2");
liste.hintenEinfuegen("Test3");
assertEquals(liste.laengeGeben(), 3);
assertEquals(liste.elementGeben(0), "Test1");
assertEquals(liste.elementGeben(1), "Test2");
assertEquals(liste.elementGeben(2), "Test3");
liste.vorneEinfuegen("Test0");
assertEquals(liste.elementGeben(0), "Test0");
assertEquals(liste.elementGeben(3), "Test3");
}
/**
* Testet primaer die Methode Liste#leeren und auf Korrektheit.
*/
@Test
public void leerenTest() {
Liste<String> liste = new Liste<String>();
assertEquals(liste.laengeGeben(), 0);
liste.hintenEinfuegen("Test1");
liste.hintenEinfuegen("Test2");
liste.hintenEinfuegen("Test3");
assertEquals(liste.laengeGeben(), 3);
liste.leeren();
assertEquals(liste.laengeGeben(), 0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment