# Verkette Liste V10



## thor_norsk (23. Nov 2021)

Guten Tag,
ich habe eine Aufgabe erhalten, und muss die Aufgabe erweitern.
Erweitern Sie die verkette 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.
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ück liefert. Alternativ können Sie sich einfach 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.

[CODE lang="java" title="Verkette Liste"]class Listenelement {

    // Instanzvariablen
    String daten;
    Listenelement naechster;   

    // Die Methode zum setzen der Daten.
    void setDaten (String datenNeu) {

    daten = datenNeu;
    naechster = null;   
    }

    void anhaengen(String datenNeu) {

    if (naechster == null) {               

        naechster = new Listenelement();     
        naechster.setDaten(datenNeu);       
        System.out.println("Daten\t"+datenNeu+"\t wurden eingefügt.");
        }
     else 
        naechster.anhaengen(datenNeu);       
     }

    void ausgeben() {

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

public class ListeV3 {

    public static void main(String[] args) {

        Listenelement listenAnfang = new Listenelement();
        listenAnfang.setDaten("Element1");

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

        listenAnfang.ausgeben();
    }
}
[/CODE]

Ich habe den Code erweitert und Einiges verändert, ich würde gerne Wissen, ob ich Alle Kriterien erfüllt habe ?

[CODE lang="java" title="Verkette Liste Erweitert"]class Listenelement {

    // Instanzvariablen
    String daten;
    Listenelement naechster;   

    //  Methode zum setzen der Daten.
    void setDaten (String datenNeu) {

    daten = datenNeu;
    naechster = null;   
    }

    // Methode zum Anhängen
    Listenelement anhaengen(String datenNeu) {

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

    // Methode zur Ausgabe
    void ausgeben() {

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

public class ListeV5 {

    public static void main(String[] args) {

        // Neues Listenelement erzeugen.
        Listenelement listenAnfang = new Listenelement(); 

        // Daten in ersten Listenelement setzen.
        listenAnfang.setDaten("Element1");

        // Neues Listenelement erzeugen.
        Listenelement listenEnde = new Listenelement();
        listenEnde = listenAnfang;

        // Weitere elemente mit der Schleife einfügen
        for (int element = 2; element < 21; element++)
            listenEnde = listenEnde.anhaengen("Element"+element);

        // Liste ausgeben
        listenAnfang.ausgeben();
    }
}
[/CODE]

Jetzt folgt noch eine Erweiterung, die nicht funktioniert. Eventuell kleiner Fehler ?
Jetzt soll die Liste auch rückwärts ausgegeben werden können.

[CODE lang="java" title="Verkette Liste rückwärts"]class Listenelement {

    // Instanzvariablen
    String daten;
    Listenelement naechster;   

    // Die Methode zum setzen der Daten.
    void setDaten (String datenNeu) {

    daten = datenNeu;
    naechster = null;   
    }

    // Methode zum Anhängen
    Listenelement anhaengen(String datenNeu) {

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

    // Methode zur Ausgabe
    void ausgeben() {

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

    // Methode zur Ausgabe Rückwärts (Rekursiv)
    void ausgebenR() {

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

public class ListeV6 {

    public static void main(String[] args) {

        // Neues Listenelement erzeugen.
        Listenelement listenAnfang = new Listenelement(); 

        // Daten in ersten Listenelement setzen.
        listenAnfang.setDaten("Element:1");

        // Neues Listenelement erzeugen.
        Listenelement listenEnde = new Listenelement();
        listenEnde = listenAnfang;

        // Weitere elemente mit der Schleife einfügen
        for (int element = 2; element < 21; element++)
            listenEnde = listenEnde.anhaengen("Element:"+element);

        // Liste ausgeben Vorwärts
             listenAnfang.ausgeben();

        // Liste ausgeben Rückwärts
            listenAnfang.ausgebenR();
    }
}
[/CODE]


----------



## temi (23. Nov 2021)

Sollte es laut Aufgabe, neben "naechster", nicht auch eine Instanzvariable "letzter" geben?

EDIT: Hab grad gesehen, dass das in der main() steht. Ich finde es allerdings schon etwas seltsam, dass das erste und letzte Element nicht Instanzvariablen der Klasse ListeVx sind, mit entsprechenden Methoden zum Anhängen usw. Aber du bist ja schon bei V10, wenn es bis dahin richtig war, wird es wohl so passen


----------



## temi (23. Nov 2021)

thor_norsk hat gesagt.:


> Jetzt folgt noch eine Erweiterung, die nicht funktioniert. Eventuell kleiner Fehler ?
> Jetzt soll die Liste auch rückwärts ausgegeben werden können.


Was passiert denn, wenn in der Ausgabemethode "naechster" null ist?


----------



## thor_norsk (23. Nov 2021)

Ich habe viele Experimente gemacht, deshalb bin ich bei V10 gelandet .
ListenAnfang & ListenEnde sind Instanzvariablen.  (siehe main())

      // Neues Listenelement erzeugen.
        Listenelement listenAnfang = new Listenelement(); 


        // Neues Listenelement erzeugen.
        Listenelement listenEnde = new Listenelement();


----------



## temi (23. Nov 2021)

thor_norsk hat gesagt.:


> ListenAnfang & ListenEnde sind Instanzvariablen. (siehe main())


Nö. Das sind lokale Variablen in der Methode main().

"daten" und "naechster" der Klasse Listenelement sind Beispiele für Instanzvariablen.


----------



## thor_norsk (23. Nov 2021)

Lokal weil ich die in der main() erzeugt habe? Ansonsten Innerhalb der Klasse wären die auch Instanzvariablen ?


----------



## temi (23. Nov 2021)

thor_norsk hat gesagt.:


> Lokal weil ich die in der main() erzeugt habe? Ansonsten Innerhalb der Klasse wären die auch Instanzvariablen ?




```
class Foo {
    private int instanzvariable;
    private static int klassenvariable; // der Vollständigkeit halber
   
    void doSomething() {
        int lokaleVariable = 0;
    }
}
```

Instanzvariable deshalb, weil es für jede Instanz, die von der Klasse erzeugt wird, eine unabhängige Variable gibt.
Lokale Variable, weil sie nur lokal, hier innerhalb der Methode, gültig ist.


----------



## thor_norsk (23. Nov 2021)

Instanz = Objektvariable ? 

Zum Beispiel:

class Autoklasse {

Autoklasse auto1 = new Autoklasse(); // Instanz1 : auto1
Autoklasse auto2 = new Autoklasse(); // Instanz2: auto2 

So habe ich gelernt, Instanzen zu erzeugen! 

Ich kann jetzt zum Beispiel auto1.gasgeben(50); aufrufen, und den alten Wert durch die Methode um 50 km/h zu erhöhen.


----------



## temi (23. Nov 2021)

thor_norsk hat gesagt.:


> Instanz = Objektvariable ?
> 
> Zum Beispiel:
> 
> ...


Ich würde eher sagen Instanz = Objekt und ja, mit new werden Instanzen einer Klasse erzeugt.


----------



## thor_norsk (23. Nov 2021)

Sie haben geschrieben (temi): Nö. Das sind lokale Variablen in der Methode main().

Wie können die Variablen lokal sein, wenn ich Instanzen der Klasse Listenelement erzeuge ?
[CODE lang="java" title="Verkette Liste Erweitert"]public static void main(String[] args) {

        // Neues Listenelement erzeugen.
        Listenelement listenAnfang = new Listenelement();

    ...........usw[/CODE]


----------



## thor_norsk (23. Nov 2021)

Nochmal : Ich erzeuge 2 Objektvariablen = Instanzen, damit ich mit der Klasse Listenelement Kommunizieren kann oder ?
Objektvariablen : listenAnfang & listenEnde


----------



## temi (23. Nov 2021)

thor_norsk hat gesagt.:


> Wie können die Variablen lokal sein, wenn ich Instanzen der Klasse Listenelement erzeuge ?


Lokale Variablen können auch die Referenz auf eine Instanz/Objekt aufnehmen.

Das hat nichts damit zu tun, *was* darin gespeichert ist, sondern an *welcher* Stelle die Variable deklariert wurde.

```
class Foo {
    private int instanzvariable;
 
    void doSomething() {
        int lokaleVariable = 0;
    }
}
```

Ist die Variable im Klassenrumpf deklariert, dann ist es eine Instanzvariable. Ist sie innerhalb einer Methode deklariert, dann ist es eine lokale Variable.


----------



## thor_norsk (23. Nov 2021)

Könnten Sie freundliche Weise Paar Beispiele zeigen, damit ich den Unterschied sehe?


----------



## temi (23. Nov 2021)

Ich habe den Beitrag darüber editiert. Es steht aber auch schon mal weiter oben.


----------



## thor_norsk (25. Nov 2021)

Guten Abend, 
Kann mir jemand Tipp geben? Ich möchte die Liste rückwärts ausgeben.


----------



## Jw456 (25. Nov 2021)

Du gehst ja bei der Ausgabe deine Liste rekursiv vorwertz durch. Dann mache halt die Ausgabe wenn du von der Methode zurück kommst.


----------



## kneitzel (25. Nov 2021)

thor_norsk hat gesagt.:


> Nochmal : Ich erzeuge 2 Objektvariablen = Instanzen, damit ich mit der Klasse Listenelement Kommunizieren kann oder ?
> Objektvariablen : listenAnfang & listenEnde


Hier bitte immer gut aufpassen!

Du hast Variablen - das sind die Elemente, in denen Du etwas speichern kannst.
Und dann gibt es Instanzen (oder Objekte wenn Du das deutsche bevorzugst). Die existieren irgendwo und Du hast da nur eine Referenz zu.
Diese Referenz kannst Du dann z.B. in einer Variable speichern.

konkretes Beispiel von Dir:
`Autoklasse auto1 = new Autoklasse();`

Das `Autoklasse auto1` ist die Deklaration der Variable. Das ist einfach nur eine Variable und je nachdem, wo es steht, ist es eine Instanz- oder eine lokale Variable.

Das `new Autoklasse()` ist die Erzeugung einer neuen Instanz und die Referenz wird zurück gegeben.
Das könnte prinzipiell auch ganz alleine ohne eine Variable da stehen.

Dann haben wir in der Zeile nur noch eine Sache: Die Zuweisung. Auf der linken Seite muss etwas stehen, dem etwas zugewiesen werden kann. Das ist hier eine Variable. Auf der rechten Seite steht ein Ausdruck - in dem Beispiel ein Ausdruck, der eine neue Instanz erzeugt.

Das sind aber zwei paar Schuhe!

Siehe Instanzen wie Häuser an. Jedes haus hat eine eindeutige Adresse (=Referenz). Und dann hast Du Dinge, da kannst Du so eine Adresse drauf schreiben - das wären dann Referenzen.

Du kannst dann eine Adresse auf einen Zettel schreiben, wo du den Zettel direkt weg wirfst ==> lokale Variable.
Du kannst die Adresse aber auch in irgend einem Haus an die Wand schreiben ==> Das hast Du dann dauerhaft in dem Haus stehen. So Du also das Haus mit der Adresse an der Wand hast, hast Du auch diese Adresse.
Und natürlich bleibt ein Haus dauerhaft stehen - auch wenn ein Zettel mit der Adresse weggeschmissen wird.


----------



## thor_norsk (25. Nov 2021)

Zuerst möchte ich mich bedanken. Da die Speicherverwaltung unter Java automatisch veranlasst wird, außer wenn man es manuell aufruft. Allerdings für mich erst Mal nicht wichtig. 
Ich werde euch noch bisschen nerven, aber ich möchte es verstehen und kein wackeliges Haus bauen.

Autoklasse auto1 = new Autoklasse(); 
Ich habe eine variable erzeugt und eine Instanz ?
Variable: auto1 (Referenz auf Instanz=Objekt)
Instanz: Irgendwo im Speicher abgelegt mit allen Eigenschaften der Autoklasse

Wenn zum Beispiel: 
class Autoklasse {

... kaufen () {.....}
...  verkaufen() {...}
}
somit kann ich auf alle Methoden der Klasse über die Variable auto1 zugreifen

auto1.kaufen();
und später
auto1.verkaufen();

Eine wichtige Frage noch:

// Methode zum Anhängen 
    Listenelement anhaengen(String datenNeu) {

        naechster = new Listenelement();  // lasse Listenelement vor naechster weg , da die Methode als Listenelement anhaegen()
                                                               // deklariert ist ? Wenn ich Listenelement naechster = new Listenelement();
                                                               // schreiben würde, wäre syntaktisch ok aber überflüssig???
        naechster.setDaten(datenNeu);
        return naechster;
        }


----------



## temi (25. Nov 2021)

`Autoklasse auto1 = new Autoklasse();`

Hier wird eine Variable auto1 vom (Referenz-)Typ Autoklasse deklariert und dieser eine Referenz auf die neu erzeugte Instanz von Autoklasse zugewiesen.


```
Listenelement anhaengen(String datenNeu) {
        naechster = new Listenelement();
        naechster.setDaten(datenNeu);
        return naechster;
    }
```

Die Instanzvariable "naechster" ist ja bereits deklariert. Wenn es das letzte Element der Liste ist, dann ist "naechster" ja *null*. Würdest du also keine Referenz auf ein neues Listenelement zuweisen, dann würde der Versuch `naechster.setDaten(datenNeu);` mit einer NullPointerException fehlschlagen.


----------



## thor_norsk (25. Nov 2021)

So ungefähr wie ich erklärt habe.

Wie ist bei der Methode anhaengen() ??? Habe ich recht oder unrecht ?

// Methode zum Anhängen 
   Listenelement anhaengen(String datenNeu) {

       naechster = new Listenelement();  // lasse Listenelement vor naechster weg , da die Methode als Listenelement anhaegen()
                                                              // deklariert ist ? Wenn ich Listenelement naechster = new Listenelement();
                                                              // schreiben würde, wäre syntaktisch ok aber überflüssig???
       naechster.setDaten(datenNeu);
       return naechster;
       }


----------



## thor_norsk (25. Nov 2021)

Habe die Methode verbessert , ich überprüfe lieber bevor ich Elemente daran hänge.

// Methode zum Anhängen 
    Listenelement anhaengen(String datenNeu) {
        if (naechster == null) {
        naechster = new Listenelement();
        naechster.setDaten(datenNeu);
            }
        return naechster;
    }


----------



## temi (27. Nov 2021)

thor_norsk hat gesagt.:


> Wie ist bei der Methode anhaengen() ??? Habe ich recht oder unrecht ?


Ich verstehe deine Frage nicht.


thor_norsk hat gesagt.:


> Wenn ich `Listenelement naechster = new Listenelement();` schreiben würde, wäre syntaktisch ok aber überflüssig???


Wenn du es weglässt erhältst du bei der Zuweisung an naechster.setDaten() einen Fehler. Hab ich doch oben geschrieben.


----------



## thor_norsk (29. Nov 2021)

Alles ok!


----------

