# Einfach verkettete Liste ändern



## OSchriever (26. Sep 2019)

Hi Freunde,
ich stehe bei einer Aufgabe zur Erweiterung der einfach verketteten Liste auf dem Schlauch:
Hier folgende Aufgabenstellung:


Erweitern Sie die zweite Version der einfach verketteten Liste so, dass das Listenende
beim Anhängen nicht immer wieder neu ermittelt werden muss, sondern neue Elemente
direkt am Ende der Liste angehängt werden können. Hängen Sie zum Test
mindestens 20 Elemente an.
Dazu ein paar Hilfestellungen:
• Sie müssen neben dem Anfang der Liste jetzt auch das Ende der Liste in einer
Variablen speichern können.
• Erstellen Sie eine Methode, die Ihnen das aktuelle Ende der Liste zurückliefert.
Alternativ können Sie sich das Listenende auch von der Methode zum Anhängen
liefern lassen.
• Setzen Sie den Wert der Variablen für das Listenende nach dem Anhängen neuer
Elemente jeweils auf das aktuelle Ende der Liste und rufen Sie dann die Methode
zum Anhängen neuer Listenelemente mit diesem Wert neu auf.

Und hier der Code:


```
//die Klasse für die Listenelemente
//jetzt auch mit Methoden
class Listenelement {
        String daten;
        Listenelement naechster;

        //die Methode zum Setzen der Daten
        void setDaten(String datenNeu) {
            //die Zeichenkette setzen
            daten = datenNeu;
            //das Ende markieren
            naechster = null;
        }

        //die Methode zum Anhängen eines neuen Elements
        //sie ruft sich rekursiv auf, bis das Ende erreicht ist
        void anhaengen(String datenNeu) {
            //wenn das Ende erreicht ist, ein neues Element erzeugen
            if (naechster == null) {
                naechster = new Listenelement();
                naechster.setDaten(datenNeu);
            }
            //sonst ruft sich die Methode selbst wieder auf
            else {
                naechster.anhaengen(datenNeu);
            }
            //nur zur Veranschaulichung
            System.out.println("Daten " + datenNeu + " wurden eingefügt.");
        }

        //die Methode zur Ausgabe der Liste
        //sie ruft sich ebenfalls rekursiv auf, bis das Ende erreicht ist
        void ausgeben() {
            System.out.println(daten);
            if (naechster != null)
                naechster.ausgeben();
        }
    }
```




```
public class Main {

    public static void main(String[] args) {
        Listenelement listenAnfang = new Listenelement();

        //die Daten im ersten Listenelement setzen
        listenAnfang.setDaten("Element 1");

        //weitere Elemente in einer Schleife einfügen
        for (int element = 2; element < 4; element++)
            listenAnfang.anhaengen("Element " + element);

        //die Liste ausgeben
        listenAnfang.ausgeben();
       

    }

}
```

--------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ich habe schon sämtliche Sachen ausprobiert wie ein 2. Objekt (listenEnde) zu erstellen, in der Main sowie in der Klasse Listenelement und dann auch versucht sie dort zu ändern bzw. das Ende neu zu setzen, aber irgendwie bekomme ich den Dreh nicht rein. Irgendwas mache ich verkehrt, nur was?


Vielen Dank im Voraus


----------



## mihe7 (26. Sep 2019)

Soll das so sein, dass Du keine Klasse für die Liste sondern nur für das Element hast?

Unabhängig davon: Du brauchst nicht nur eine Variable für den listenAnfang, sondern auch für das listenEnde. Zu Beginn ist listenEnde = listenAnfang. Zum Anhängen verwendest Du dann einfach listenEnde in der Weise: `listenEnde = listenEnde.anhaengen("Element " + element);`. In dem Fall muss die Methode anhaengen() natürlich das neue Listenende zurückgeben.

Probiers einfach nochmal


----------



## flopalko (27. Sep 2019)

Ich gebe dir auch noch ein Grundgerüst mit dem du arbeiten kannst:


```
public class Liste{
    Listenelement anfang;
    Listenelement ende;
    
    //Methoden zum Verwalten der Liste   

    private class Listenelement{
        String daten;
        Listenelement naechster;
        
        //Methoden für ein Listenelement   
    }
}
```


----------



## OSchriever (28. Sep 2019)

Vielen Dank, habs hinbekommen


----------



## OSchriever (28. Sep 2019)

mihe7 hat gesagt.:


> Soll das so sein, dass Du keine Klasse für die Liste sondern nur für das Element hast?
> 
> Unabhängig davon: Du brauchst nicht nur eine Variable für den listenAnfang, sondern auch für das listenEnde. Zu Beginn ist listenEnde = listenAnfang. Zum Anhängen verwendest Du dann einfach listenEnde in der Weise: `listenEnde = listenEnde.anhaengen("Element " + element);`. In dem Fall muss die Methode anhaengen() natürlich das neue Listenende zurückgeben.
> 
> Probiers einfach nochmal


Ja das soll so sein, ist halt ne Anfängeraufgabe aus nem Kurs


----------



## Albi_2020 (19. Jun 2020)

Ich habe das gleiche Problem mit dieser Aufgabe....allerdings habe ich eh noch so meine Schwierigkeiten mit der objektorientierten Programmierung...wie habt ihr das im Code implementiert...? Irgendwie benötige ich mal einen richtigen Schlag vor den Kopp  

LG
Albi


----------



## mihe7 (19. Jun 2020)

Wo hakts denn?


----------



## Kirby.exe (19. Jun 2020)

Albi_2020 hat gesagt.:


> Ich habe das gleiche Problem mit dieser Aufgabe....allerdings habe ich eh noch so meine Schwierigkeiten mit der objektorientierten Programmierung...wie habt ihr das im Code implementiert...? Irgendwie benötige ich mal einen richtigen Schlag vor den Kopp
> 
> LG
> Albi


Also prinzipiell ist es gar nicht so schwer zu verstehen  Das Konzept ist, dass du im Grunde einen "Haupt" Kontainer hast, nämlich deine Liste. Diese Liste enthält wiederum Kontainer (ListenElemente), welche dann eine Referenz auf das nächste ListenElement enthalten und noch eine Instanzvariable für ein Objekt, also für den eigentlichen Inhalt, welchen ihr mit dieser Liste verwalten wollt


----------



## Albi_2020 (19. Jun 2020)

Ich fasse mal kurz zusammen:

zunächst wird eine Instanz erzeugt, die den Listenanfang kennzeichnet. Mit der Referenz von listenAnfang wird die Methode setDaten() aufgerufen und der String "Element 1" übergeben. Anschließend besitzt das 1. Element die Werte Daten = Element1 und naechster = null.

Nun werden neue Elemente über die for-Schleife zugefügt und jeweils die Durchlaufnummer als String übergeben. Die Referenz von listenAnfang ruft dabei die Methode anhaengen() auf. Da es bisher nur ein Element gibt, ist naechster == null und die if-Schleife wird durchlaufen.
Ein weiteres Element wird erzeugt und als Referenz in naechster gespeichert --> listenAnfang zeigt nun auf das neue Element. Die neue Referenz ruft die Methode setDaten() auf und speichert daten = Element 2 und naechster = null.
Beim zweiten Durchlauf der Schleife ist ja naechster für listenAnfang nicht mehr null, sondern die Referenz auf das zuvor eingefügte Element. dadurch wird der else-Zweig durchlaufen. Die Referenz des 2. Objekts ruft die Methode rekursiv auf und speichert daten = Element 3 und naechster = null....u.s.w.

Soweit habe ich das auch verstanden. Ich tue mich nun nur schwer, die Referenz vom letzten Element zu speichern (wie bekomme ich die Referenz und nicht das null) und vor allem wo setzte ich diese Information ein.

LG
Albi


----------



## Kirby.exe (19. Jun 2020)

Naja also die Referenz der Vorgängers muss nur bei DoubleLinkedLists verwaltet werden, da dort in beide Richtungen iterieren kann. Bei einer SingleLinkedList (einfach verkettet) muss nur der Nachfolger gemerkt werden, da nur vom listenAnfang bis zu null iteriert wird  Welche Liste möchtest du den gerne implementieren?


----------



## mihe7 (19. Jun 2020)

Albi_2020 hat gesagt.:


> if-Schleife





			if-schleife.de


----------



## Kirby.exe (19. Jun 2020)

mihe7 hat gesagt.:


> if-schleife.de


Das Meme wird irgendwie nie langweilig xD


----------



## mihe7 (19. Jun 2020)

Kirby_Sike hat gesagt.:


> Das Meme wird irgendwie nie langweilig xD


Das stirbt einfach nicht aus.


----------



## Albi_2020 (19. Jun 2020)

Die gleiche Aufgabe wie von OSchrieber......sorry ja if-Abfrage


----------



## Kirby.exe (19. Jun 2020)

Er behandelt nur eine Single Linked List und somit musst du dir deinen Vorgänger nicht merken


----------



## mihe7 (20. Jun 2020)

Albi_2020 hat gesagt.:


> Ich tue mich nun nur schwer, die Referenz vom letzten Element zu speichern (wie bekomme ich die Referenz und nicht das null) und vor allem wo setzte ich diese Information ein.


Mal von hinten angefangen: das Listenende kannst Du Dir merken, damit Du schnell ein Element ans Ende hängen kannst und nicht mehr erst durch die ganze Liste iterieren musst. Dazu muss anhaengen() lediglich dahingehend angepasst werden, dass die Methode das neue Listenende zurückgibt. Die Verwendung läuft dann wie unter #2 beschrieben.


----------



## Albi_2020 (21. Jun 2020)

Habe den Code folgendermaßen geändert:

neuer Code:

class Listenelement {
String daten;
Listenelement naechster;

void setDaten(String datenNeu) {
daten = datenNeu;
naechster = null;
}

Listenelement anhaengen(String datenNeu) {

naechster = new Listenelement();
naechster.setDaten(datenNeu);
return naechster;
}

void ausgeben() {
System.out.println(daten);
if (naechster != null)
naechster.ausgeben();
}
}


Java:
public class Main {

public static void main(String[] args) {
Listenelement listenAnfang = new Listenelement();

listenAnfang.setDaten("Element 1");

Listenelement listenEnde = listenAnfang;

for (int element = 2; element < 4; element++)
listenEnde = listenEnde.anhaengen("Element " + element);

listenAnfang.ausgeben();


}

}


----------



## mihe7 (21. Jun 2020)

Albi_2020 hat gesagt.:


> Habe den Code folgendermaßen geändert:


Code bitte in Code-Tags posten (die drei Punkte neben dem Smiley, dort auf Code, dann Java auswählen und den Quelltext inkl. Einrückungen in das Textfeld einfügen).

Und, funktionierts?


----------



## Albi_2020 (21. Jun 2020)

ja funktioniert...super danke....wäre ich alleine nicht drauf gekommen


----------



## DocSnyder1 (3. Feb 2021)

Hey, nun hänge ich auch bei der Aufgabe fest. Kann mir da einer nochmal helfen. Komme mit den zuvor geschriebenen posts nicht ganz klar. Vielen Dank


----------



## DocSnyder1 (3. Feb 2021)

Hey, nun hänge ich auch bei der Aufgabe fest. Kann mir da einer nochmal helfen. Komme mit den zuvor geschriebenen posts nicht ganz klar. Vielen Dank


----------



## Kirby.exe (3. Feb 2021)

DocSnyder1 hat gesagt.:


> Hey, nun hänge ich auch bei der Aufgabe fest. Kann mir da einer nochmal helfen. Komme mit den zuvor geschriebenen posts nicht ganz klar. Vielen Dank


Wobei hängst du denn fest?


----------



## DocSnyder1 (3. Feb 2021)

Leider generell bei der ganzen Thematik und Aufgabe. Weiß gar nicht wo ich die Aufgabe richtig anpacken soll. Die Methode "anhängen" muss ja ziemlich eingestampft werden denke ich. Die if else Abfrage ist ja nicht mehr nötig. Da muss ja nur noch das neue Element angehangen werden und dann das neue Listenende uU in einer Variablen fixiert werden. Da frage ich mich nun bloß ob man hier wie zuvor einmal geschrieben eine eigene Klasse erzeugt werden muss wo der Endwert dann mitrolliert....kp...ich bin völlig lost gerade. Diese ganze Rekursionsthematik sprengt auch einfach meinen Kopf.


----------



## Kirby.exe (3. Feb 2021)

Also stell dir das so vor, dass du einen Container Liste hast und diese Liste enthält Elemente vom Typ ListenElement. Dieses ListenElement hat eine Referenz auf seinen Nachfolger. Deine Liste hat eine Instanzvariable mit der Referenz auf das erste Element in der List.

So wäre es bei deiner Single Linked List.

Natürlich kannst du noch eine Instanzvariable haben welche auf das Ende der Liste zeigt.

Nun musst du in deiner Methode anhaenge folgendes tun:

Prüfe ob die Variable für den Anfang deiner Liste null ist, wenn ja dann weise Ihr das einzufügende Element zu.

Ansonsten iteriere durch die Liste bis der nächste Nachbar des aktuellen Elements null ist und hänge das aktuelle Element an.


----------



## Jonas_E (3. Mrz 2021)

Hier mal ein Beispiel von mir:


```
class Listenelement {
    String daten;
    Listenelement next;

    // die Methode zum setzen der Daten
    void setDaten(String datenNeu) {
        // die Zeichenkette setzen
        daten = datenNeu;
        // das Ende markieren
        next = null;
    }

    // die Methode zum Anhängen eines neuen Elements
    // am Ende der Liste
    Listenelement anhaengen(String datenNeu) {
        next = new Listenelement();
        next.setDaten(datenNeu);
        return next;
    }

    void ausgeben() {
        System.out.println(daten);
        if (next != null) {
            next.ausgeben();
        }
    }

    // Methode zum Rekursiven Rückwärtslauf
    void ausgebenRev() {
        if (next != null) {
            next.ausgeben();
            System.out.println(daten);
        }
    }

}

public class Main {

    public static void main(String[] args) {
        // ein neues Listenelement erzeugen
        Listenelement listenAnfang = new Listenelement();

        // die Daten im ersten Listenelement setzen
        listenAnfang.setDaten("Element 1 / Kopf");

        // Das Listenende entspricht dem Listenanfang
        Listenelement listenEnde = listenAnfang;

        // weitere Elemente in einer Schleife einfügen
        for (int element = 2; element < 31; element++)
            listenEnde = listenEnde.anhaengen("Element laufend " + element);

        // Die Liste ausgeben normal
        listenAnfang.ausgeben();
        // Die Liste rückwärts ausgeben
        listenAnfang.ausgebenRev();
    }

}
```


----------



## kneitzel (3. Mrz 2021)

Das sieht recht dubios aus. setDaten sollte daten setzen. Das besagt der Name. Warum macht es noch mehr?


----------



## Jonas_E (3. Mrz 2021)

kneitzel hat gesagt.:


> Das sieht recht dubios aus. setDaten sollte daten setzen. Das besagt der Name. Warum macht es noch mehr?


Weil ich diesen Code selbst letztens verwendet habe und vergessen habe die Sachen, die hier nicht benötigt werden rauszunehmen


----------



## melro (17. Feb 2022)

Jonas_E hat gesagt.:


> Hier mal ein Beispiel von mir:
> 
> 
> ```
> ...


Es tut mir wirklich sehr leid, dass ich so blöd fragen muss: aber warum wird die Methode anhaengen plötzlich zu einem Listenelement? 

Vielen Dank im Vorhinein!


----------



## Kirby.exe (17. Feb 2022)

Weil du ja das aktuelle auf das neue Zeigen läst per Referenz und dann das nächste zurück gibst  Damit hast du also das aktuell letzte Element in der Kette


----------



## melro (17. Feb 2022)

melro hat gesagt.:


> Es tut mir wirklich sehr leid, dass ich so blöd fragen muss: aber warum wird die Methode anhaengen plötzlich zu einem Listenelement?
> 
> Vielen Dank im Vorhinein!


Ich glaub ich muss meine Frage anders formulieren: zuerst war die methode: void anhaengen.... jetzt ist es Listenelement anhaengen:
wieso heißt es jetzt plötzlich Listenelement und nicht mehr void? Nur weil schlüsselwort void kein return hat?

Vielen Dank im Vorhinein!


----------



## mihe7 (17. Feb 2022)

melro hat gesagt.:


> Ich glaub ich muss meine Frage anders formulieren: zuerst war die methode: void anhaengen.... jetzt ist es Listenelement anhaengen:
> wieso heißt es jetzt plötzlich Listenelement und nicht mehr void? Nur weil schlüsselwort void kein return hat?
> 
> Vielen Dank im Vorhinein!


s. Kommentar #16


----------



## Knausbär (14. Jun 2022)

Jonas_E hat gesagt.:


> Hier mal ein Beispiel von mir:
> 
> 
> ```
> ...


Hallo,

nur für die Richtigkeit die Methode zum Rückwärts ausgeben der Liste müsste so aussehen:


```
// Methode zum Rekursiven Rückwärtslauf
    void ausgebenRev() {
        if (next != null)             
            next.ausgebenRev();           
        System.out.println(daten);
    }
```


----------



## Naiklay (17. Jun 2022)

Hallo zusammen, jetzt habe ich auch nochmal eine Verständnisfrage dazu: Wenn ich den Code ausführe, dann erscheinen bei mir die Elemente nicht in der umgekehrten Reihenfolge. Das Element 1 /Kopf steht zwar am Ende, aber zuvor wird die Liste in der richtigen Reihenfolge ausgegeben. Muss das nicht auch in der anderen Reihgenfolge erfolgen?


----------



## mihe7 (17. Jun 2022)

@Naiklay, s. Antwort von @Knausbär. Der Fehler war, dass ausgebenRev nicht rekursiv aufgerufen wurde.


----------



## blaBra (17. Jun 2022)

hm, ist heute Tag der wandelnden Leichen?! Der initiale Beitrag ist 3 Jahre her.


----------



## Naiklay (17. Jun 2022)

mihe7 hat gesagt.:


> @Naiklay, s. Antwort von @Knausbär. Der Fehler war, dass ausgebenRev nicht rekursiv aufgerufen wurde.


Ah jetzt habe ich den Fehler entdeckt. Manchmal sind es einfach die kleinen Dinge. Vielen Dank für deine Antwort.


----------



## Brpo25 (16. Aug 2022)

Hallo Leute, 
habe auch ein Problem damit. Also bei mir funktioniert alles, ich verstehe auch dem Code aber eine Sache macht mich fertig und das ist die Referenz 😵. Also "ListenElement hat eine Referenz auf seinen Nachfolger" oder  "Der Typ dieser Instanzvariablen entspricht dabei der Klasse. Das heißt also, eine Instanz der Klasse kann eine Referenz auf eine andere Instanz der Klasse speichern." und das bedeutet, dass "naechster " immer die Referenz auf sein Nachfolger mit dem "null" speichert, und löscht damit der wert null beim letzten Element und das komplett automatisch, und dass immer, wenn wir so eine Instanz erzeugen?
Und bei der Ausgabe wird automatisch durch alle Elemente durchgesucht, wegen der Referenz. Ungefähr wie bei for-Schleife?
Verstehe ich da so richtig?😬


----------



## KonradN (16. Aug 2022)

Es kann durchaus sein, dass Du das Richtige meinst. Aber das klingt so, wie Du es schreibst, zumindest auf mich etwas wirr.

Klassen sind Referenz Typen, d.h. Du bekommst eine Referenz. Das heisst, bei einer Variable mit dem Typ einer Klasse hast Du dann eine Variable, die eine Referenz speichern kann.
Bei einer Zuweisung muss die Referenz dem Typ "entsprechen" oder der Null-Referenz. Entsprechen bedeutet, dass die Instanz entweder vom Typ der Referenz ist oder der Typ der Referenz von dem Typ erbt.

Was dann auch etwas durchklingt: Wenn Du eine neue Instanz erzeugst, die Instanzvariablen enthält, dann werden diese initialisiert. Das nenne ich gerne Nullwerte. int, long, byte, ... sind 0. float / double 0.0  ... boolean ist false, Referenzen sind null (Die Null-Referenz).

Bezüglich dem durchgehen: Das ist üblicherweise eine Schleife. Wie diese Schleife aussieht, ist dabei egal: for-schleife, while-Schleife, Rekursion .... So Schleifen sind auch ineinander umwandelbar.


----------



## Jw456 (16. Aug 2022)

und das bedeutet, dass "naechster " immer die Referenz auf sein Nachfolger mit dem "null"

Null ist der nechste nur wenn ein neues Element angegangen wird.
Ein neuer Wagen am Zug. Im dem neuen Wagen ist es dann Null. 

Das neue Element trägt ja dann seine ref in das vorherige Element ein bei naechster.

Nur der letzte Wagen vom Zug hat eine Null  Ref in der Variablen naechster.


----------



## Brpo25 (16. Aug 2022)

Ach so, jetzt bin ich bisschen näher aber... ja neue Instanz bekommt null, ist mir klar. Aber wenn dann die zweite Instanz erzeugt wird, dann bekommt die automatisch der Null Wert von der erste wo gelöscht wird?

Und die Schleife, ja ok. Die funktioniert halt so, werde ich mir merken.

Oder der Null Wert wandert einfach mit dem "naechster" durch alle Instanzen? Und dann genauso auch in der Schleife bei der Ausgabe?


----------



## kalter_Tofu (25. Aug 2022)

Hallo,

ich habe ein Programm nach dem Muster der Aufgabe im ersten Post geschrieben und ein paar Probleme.

1) Die Version, in der die Methode zum Anhängen das Listenende liefert, funktioniert. Aber den Teil "Erstellen Sie eine Methode, die Ihnen das aktuelle Ende der Liste zurückliefert." bekomme ich nicht hin, und ich will lernen, wie das funktioniert.

2) Vorwärts wird die Liste vollständig angezeigt, also A bis F. Aber rückwärts wird E bis A ausgegeben. Warum fehlt das F, was habe ich bei der Rückwärtsausgabe übersehen?

3) Ein kleineres Problem ist die Ausgabe der Bezeichnung, bzw. die for-Schleife. 
for (char bezeichnung = 'B'; bezeichnung <= 'Z'; bezeichnung++) oder for (int bezeichnung = 2; bezeichnung <= 20; bezeichnung++) funktioniert.
Die Bezeichnungen lauten aber normalerweise A.1.b, 3.24.1.3. oder so ähnlich. Kann ich diese Bezeichnungen in die for-Schleife einbauen, oder müsste ich für eine Liste mit Bezeichnungen dieser Art was anderes schreiben?

Frage an die Experten: Habt ihr Tipps und Hinweise, wie ich die Fehler beheben kann?



```
/* ~~Fibeltypen~~
 * einfach verkettete Liste
 * vorwärts ausgeben 
 * rückwärts ausgeben
 * neue Einträge direkt am Listenende einfügen
 */

package fibeltypen;

//Klasse (Bauplan) für die Fibeltypen
class FibeltypVer2 {
    // Instanzvariable für Beschreibung eines Fibeltyps
    String beschreibung;
    // Instanzvariable für den folgenden Fibeltyp
    FibeltypVer2 neuerTyp;
    //Instanzvariable für den letzten Fibeltyp der Liste
    FibeltypVer2 letzter;

    // Instanzmethode zum Setzen der Beschreibung
    void setBeschreibung(String beschreibungNeu) {
        // Beschreibung eines neuen Typs
        beschreibung = beschreibungNeu;
        // Markierung Listendende (=>neuerTyp ist leer)
        neuerTyp = null;
    }

    // Methode zum Anhängen eines neuen Eintrags am Listenende
    void typAnhaengen(String beschreibungNeu) {
        // neuen Typ erzeugen
        neuerTyp = new FibeltypVer2();
        // Beschreibung für den neuen Typ setzen
        neuerTyp.setBeschreibung(beschreibungNeu);
    }
    

        // Instanzmethode zur Ausgabe des Fibeltypen am Listenende
         void typAusgeben() {
            // muss hier stehen, damit von Anfang bis Ende ausgegeben wird
            System.out.println(beschreibung);
            // neuer Typ vorhanden (=> Variable neuerTyp ist nicht leer)
            if (neuerTyp != null) {
                // neuer Typ wird ausgegeben
                neuerTyp.typAusgeben();
            }
        }
    
        
    //~~~~~~~~~~~~~~~~~~~hier ist mein Problem~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // Methode zur Rückgabe des letzten Listeneintrags
        Fibeltyp2 letzterEintrag( ) {
                
         //letzter ist der Fibeltyp am Listenende
         letzter = neuerTyp;
         //letzter Eintrag wird zurückgegeben
         return letzter;
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     

        
        // Fibeltypen von Listenende zum Listenanfang ausgeben
        void typRueckw() {
            // letzter Eintrag in der Liste Fibeltypen
            if (neuerTyp != null) {
                // letzter Typ wird ausgegeben
                neuerTyp.typRueckw();
                // muss hier stehen, damit von Ende bis Anfang ausgegeben wird
                System.out.println(beschreibung);
            }
        }
    }

public class fibeltypenVersion2 {

    public static void main(String[] args) {
        // neues Element für die Liste Fibeltyp erzeugen
                FibeltypVer2 erster = new FibeltypVer2();
                // Beschreibung im ersten Element der Liste Fibeltyp setzen (=> Listenanfang)
                erster.setBeschreibung("Fibeltyp A");
                /*
                 * letzter Eintrag in der Liste entspricht dem Listenanfang, an den neue
                 * Einträge angehängt werden
                 */
                FibeltypVer2 letzter = erster;
                
        //~~~~~~~~~~~~~~~~~~~~~~hier das kleinere Problem~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                // weitere Fibeltypen in einer Schleife einfügen
                for (char bezeichnung = 'B'; bezeichnung <= 'Z'; bezeichnung++)
                //dieser Teil fehlt, weil ich die Methode für das aktuelle Listenende noch fehlt
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                          

                // Fibeltypen vorwärts ausgeben
                erster.typAusgeben();
                System.out.println("--------");
                // Fibeltypen rückwärts ausgeben
                erster.typRueckw();
            }
        }
```


----------



## KonradN (25. Aug 2022)

Generell kann es ratsam sein, einen eigenen, neuen Thread zu erstellen. Das aber nur als kleiner Hinweis.



kalter_Tofu hat gesagt.:


> 1) Die Version, in der die Methode zum Anhängen das Listenende liefert, funktioniert. Aber den Teil "Erstellen Sie eine Methode, die Ihnen das aktuelle Ende der Liste zurückliefert." bekomme ich nicht hin, und ich will lernen, wie das funktioniert.


Also erst einmal: Das mit dem Anhängen an das Listenende sehe ich nicht. Wo hast Du denn den Code, der das angeblich macht? Ich vermute, dass Du das manuell machst, damit es klappt, aber nicht über eine dedizierte Methode.

Generell musst Du Dir Überlegen, was denn passieren muss. Dazu malst Du Dir einfach einmal eine Liste auf. Du hast also z.B.:

Liste --> [A]->*->null
wobei --> die Referenz zum ersten Listenelement ist und -> jeweils die neuerTyp Referenz.

Was ist da zu machen?



kalter_Tofu hat gesagt.:



			2) Vorwärts wird die Liste vollständig angezeigt, also A bis F. Aber rückwärts wird E bis A ausgegeben. Warum fehlt das F, was habe ich bei der Rückwärtsausgabe übersehen?
		
Zum Vergrößern anklicken....

Schau Dir an, wo die Ausgabe gemacht wird. Die Ausgabe ist bei dir mit im if Block, d.h. es wird nur erfolgen, wenn es auch einen Nachfolger gibt.




kalter_Tofu hat gesagt.:



			Die Bezeichnungen lauten aber normalerweise A.1.b, 3.24.1.3. oder so ähnlich. Kann ich diese Bezeichnungen in die for-Schleife einbauen, oder müsste ich für eine Liste mit Bezeichnungen dieser Art was anderes schreiben?
		
Zum Vergrößern anklicken....

Das Problem ist, dass die Operatoren + <= und so nur für primitive Typen definiert sind in Java. Daher kannst Du da mit char und int arbeiten. So zusammengesetzte Dinge hast Du da aber nicht, daher musst Du da selbst etwas bauen. Und statt Operatoren kannst Du da dann Methodenaufrufe verwenden.*


----------



## kalter_Tofu (25. Aug 2022)

Danke für die schnelle Antwort. 
Ich habe die Frage hier gestellt, weil mein Programm auch eine verkettete Liste ist, wie die im ersten Beitrag.
Wenn ihr wollt, könnt ihr meine Fragen gern abtrennen und in einen eigenen Thread verschieben.

zu 1)
Hier die erste Version, die funktioniert:
 Die  Methode zum Anhängen eines neuen Eintrags am Listenende und zur Rückgabe eines neuen Eintrags habe ich markiert.


```
/* ~~Fibeltypen~~
 * einfach verkettete Liste
 * vorwärts ausgeben 
 * rückwärts ausgeben
 * neue Einträge direkt am Listenende einfügen
 */

package fibeltypen;

//Klasse (Bauplan) für die Fibeltypen
class Fibeltyp {
    // Instanzvariable für Beschreibung eines Fibeltyps
    String beschreibung;
    // Instanzvariable für den folgenden Fibeltyp
    Fibeltyp neuerTyp;

    // Instanzmethode zum Setzen der Beschreibung
    void setBeschreibung(String beschreibungNeu) {
        //Beschreibung eines neuen Typs
        beschreibung = beschreibungNeu;
        // Markierung Listendende (=>neuerTyp ist leer)
        neuerTyp = null;
    }

//~~~~~~hier~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Methode zum Anhängen eines neuen Eintrags am Listenende
    //und zur Rückgabe eines neuen Eintrags
    Fibeltyp typAnhaengen (String beschreibungNeu) {
        // neuen Typ erzeugen
        neuerTyp = new Fibeltyp();
        // Beschreibung für den neuen Typ setzen
        neuerTyp.setBeschreibung(beschreibungNeu);
        // Eintrag neuerTyp wird zurückgegeben
        return (neuerTyp);
    }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    // Instanzmethode zur Ausgabe des Fibeltypen am Listenende
    void typAusgeben() {
        // muss hier stehen, damit von Anfang bis Ende ausgegeben wird
        System.out.println(beschreibung);
        // neuer Typ vorhanden (=> Variable neuerTyp ist nicht leer)
        if (neuerTyp != null) {
            // neuer Typ wird ausgegeben
            neuerTyp.typAusgeben();
        }
    }

    // Fibeltypen von Listenende zum Listenanfang ausgeben
    void typRueckw() {
        // letzter Eintrag in der Liste Fibeltypen
        if (neuerTyp != null) {
            // letzter Typ wird ausgegeben
            neuerTyp.typRueckw();
            // muss hier stehen, damit von Ende bis Anfang ausgegeben wird
            System.out.println(beschreibung);
        }
    }
}

public class Fibeltypen {

    public static void main(String[] args) {

        // neues Element für die Liste Fibeltyp erzeugen
        Fibeltyp erster = new Fibeltyp();
        // Beschreibung im ersten Element der Liste Fibeltyp setzen (=> Listenanfang)
        erster.setBeschreibung("Fibeltyp A");
        
        // letzter Eintrag in der Liste entspricht dem Listenanfang
        Fibeltyp letzter = erster;
        
//~~~~~~~~und hier~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // weitere Fibeltypen in einer Schleife einfügen
        for (char bezeichnung = 'B'; bezeichnung <= 'F'; bezeichnung++)
            letzter = letzter.typAnhaengen("Fibeltyp " + bezeichnung);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        // Fibeltypen vorwärts ausgeben
        erster.typAusgeben();
     
  System.out.println("--------");

        // Fibeltypen rückwärts ausgeben
        erster.typRueckw();
    }
}
```

zu 2) Das F fehlt also bei der Rückwärtsausgabe, weil der Nachfolger fehlt. Daran hatte ich schon gedacht aber den Gedanken wieder verworfen, weil ich dachte, dass die Rückwärtsausgabe genauso funktioniert wie die Vorwärtsausgabe. 
Ich brauche hier sozusagen einen leeren Platz, auf dem ich stehe, damit ich das F beim Rückwärstgehen betreten kann. Ohne diesen leeren Platz stehe ich auf dem F und mache den ersten Schritt auf dem E. Kann man das so sagen?

Ich werde mal eine while-Schleife statt if-Abfrage testen und mir eine Lösung einfallen lassen. Version 1 des Programms funktioniert, aber ich will wissen, wie die Methode, die das aktuelle Listendende zurückliefert, gebaut wird. Vielleicht mache ich hier aber auch einen Denkfehler und muss mehr ändern, als ich dachte.

zu 3) Wenn ich mehr kann, werde ich für diese Liste Methoden basteln. Das Endziel bei dieser Aufgabe ist ein Programm, in das man archäologische Funde eintragen kann, mit Fundart, Fundort, Datierung, Beschreibung und Literatur, um Funde dann sortieren und einzeln oder als Liste auszugeben. Oder Sammelkarten oder Videospiele, geordnet nach anderen Kriterien.


----------



## KonradN (25. Aug 2022)

Also vielleicht habe ich mich bei 1) nicht gut ausgedrückt: Dein Code macht nicht das Hinzufügen ans Ende. Dein Code überschreibt den Nachfolger und ersetzt diesen mit dem neuen Eintrag. Also wenn Du hast A->B-> null und Du nun aus A deine Methode aufrufst um C ans Ende zu hängen, dann hast Du A->C->null und nicht das erwartete A->B->C->null

Zu 2) Ja, es funktioniert genau so wie bei der Vorwärts-Ausgabe. In der Vorwärtsausgabe hast Du:

Ausgabe
Prüfung
--> Rekursiver Aufruf.

Du hast bei der Rückwärtsausgabe aber:
- Prüfung
--> rekursiver Aufruf
--> Ausgabe

Den Unterschied von
- Ausgabe (Wird direkt in der Methode aufgerufen)
--> Ausgabe (Wird nur bei Prüfung aufgerufen)
siehst Du?

Wenn Du nur die Ausgabe nach hinten machen willst, dann wäre es somit:
- Prüfung
--> rekursiver Aufruf
- Ausgabe

Die Ausgabe darf also nicht innerhalb des if Blocks sein.


----------

