LinkedList implementieren

Annalena123

Aktives Mitglied
Hallo , ich muss mit gegebene methoden (gibNachfolger,gibPerson,setzeNachfolger()) , die im Anhang zu finden sind , die Lücken in den methoden FuegeEin und entferne ausfüllen .Ich weiß nicht, wie ich dies genau implementieren kann, damit Linkedlist genau funktioniert ! Kann jemand mir bitte helfen ? Ich bedanke mich im Voraus !

class LinkedPersonListe
{
// Der Kopf der verketteten Liste
private LinkedPersonKnoten _listenkopf;

// Die logische Laenge der Liste (Kardinalitaet).
private int _anzahlPersonen;

/**
* Initialisiert eine neue LinkedPersonListe.
*/
public LinkedPersonListe()
{
_listenkopf = new LinkedPersonKnoten();
_anzahlPersonen = 0;
}

/**
* Gib die Person der angegebenen Position zurueck. Bei einer ungueltigen
* Position wird null zurueckgegeben.
*
* @param position Die Position der Person, die zurueckgeben werden soll.
* @Return die Person an der Position <code>position</code>.
*/
public Person gibPerson(int position)
{
if(!istGueltigePosition(position)) return null;
LinkedPersonKnoten knoten = gibKnoten(position);

return knoten.gibPerson();
}

/**
* Gib die Laenge der Liste zurueck.
*
* @Return Anzahl der Personen in der Liste.
*/
public int gibLaenge()
{
return _anzahlPersonen;
}

/**
* Fuege eine Person an der Position position in die Liste
* ein. Alle folgenden Eintraege werden um eine Position verschoben.
* Wenn position gleich der Laenge der Personenliste ist, dann
* fuege die Person am Ende an. Wenn die Person null ist oder die
* Position ungueltig, bleibt die Liste unveraendert.
*
* @param person Die einzufuegende Person (darf nicht null sein).
* @param position Die Position, an welcher die Person eingefuegt werden soll.
*/
public void fuegeEin(Person person, int position)
{
if(person == null) return;
if(!istGueltigeEinfuegePosition(position)) return;

LinkedPersonKnoten links = ................................ ;
LinkedPersonKnoten neu = ..................................... ;
...............................................;
++_anzahlPersonen;
}

/**
* Entferne die Person an der angegebenen Position. Alle folgenden Eintraege
* werden um eine Position verschoben. Bei einer ungueltigen Position
* bleibt die Liste unveraendert.
*
* @param position Die Position der Person, der entfernt werden soll.
*/
public void entferne(int position)
{
if(!istGueltigePosition(position)) return;
LinkedPersonKnoten links = ....................... ;
LinkedPersonKnoten rechts =......................... ;
......................................;

--_anzahlPersonen;
}

/**
* Entferne alle Personen aus der Liste.
*/
public void leere()
{
_listenkopf=null ;
_anzahlPersonen = 0;
}

/**
* Bestimmt ob die uebergebene Position gueltig ist.
*
* @param position fuer den Listenzugriff
* @Return ist die Position gueltig [0 - n-1]
*/
private boolean istGueltigePosition(int position)
{
return 0 <= position && position < _anzahlPersonen;
}

/**
* Bestimmt ob die uebergebene Position eine gueltige Einfuegeposition ist.
*
* @param position fuer das Einfuegen
* @Return ist die Position gueltig [0 - n]
*/
private boolean istGueltigeEinfuegePosition(int position)
{
return 0 <= position && position <= _anzahlPersonen;
}

/**
* Gibt den Knoten an der Position position zurueck. Damit die Liste nach links
* durch den Listenkopf und nach rechts durch null abgegrenzt ist, werden bei
* ungueltigen Positionen die jeweils naeherliegende Grenze der Liste zurueckgegeben.
*
* @param position die gewuenschte Position des zurueckzugebenden Knotens
* @Return der LinkedPersonKnoten an der gewuenschten Position
* im Fall (position < 0) _listenkopf,
* im Fall (position >= _anzahlPersonen) null
*/
private LinkedPersonKnoten gibKnoten(int position)
{
if(position < 0) return _listenkopf;
if(position >= _anzahlPersonen) return null;

LinkedPersonKnoten knoten = _listenkopf;
for (int i = 0; i <= position; ++i)
{
knoten = knoten.gibNachfolger();
}
return knoten;
}
}
 

Anhänge

Bei der Programmierung ist es immer das Gleiche:
  • Als erstes muss man den Algorithmus verstehen.
  • Erst dann kann man etwas programmieren.

Daher: Beschreibe doch erst einmal, wie das Einfügen funktioniert. Kannst Du das in Worten beschreiben? Wie gehst Du vor?

Und bei so Dingen ein wichtiger Tipp: Mal es Dir auf! Du kannst ja auch einem Zettel paar Nodes der LinkedList aufzeichen und diese "nächster" Beziehung mit einem Pfeil abbilden. Dann wird es einfacher sich zu überlegen, wie das Einfügen funktionieren kann.
 
Bei der Programmierung ist es immer das Gleiche:
  • Als erstes muss man den Algorithmus verstehen.
  • Erst dann kann man etwas programmieren.

Daher: Beschreibe doch erst einmal, wie das Einfügen funktioniert. Kannst Du das in Worten beschreiben? Wie gehst Du vor?

Und bei so Dingen ein wichtiger Tipp: Mal es Dir auf! Du kannst ja auch einem Zettel paar Nodes der LinkedList aufzeichen und diese "nächster" Beziehung mit einem Pfeil abbilden. Dann wird es einfacher sich zu überlegen, wie das Einfügen funktionieren kann.
Danke für deine Antwort ! Ja natürlich! nehmen wir an wir haben 3 Elementen und zwischen 2 und 3 sollte man ein Neues platzieren ! Da muss Element 2 nicht mehr eine Referenz auf 3 haben sondern auf das Neue Element hinweisen ! Der Nachfolger von 2 wird das Neue Element sein und das neue Element referenziert auf Nummer 3 ! Ich weiß nicht was mit links so genau gemeint ist .Leider funktioniert das immer noch nicht!
public void fuegeEin(Person person, int position)
{
if(person == null) return;
if(!istGueltigeEinfuegePosition(position)) return;

LinkedPersonKnoten links = _listenkopf ;
LinkedPersonKnoten neu = _listenkopf.gibNachfolger();
links.setzeNachfolger(neu);
++_anzahlPersonen;
}
 
Bitte verwende doch zum Einfügen von Code die Code-Tags: Das Symbol </> ganz links im Beitragseditor.
Java:
public void fuegeEin(Person person, int position) {
    if(person == null) return;
    if(!istGueltigeEinfuegePosition(position)) return;

    LinkedPersonKnoten links = _listenkopf ;
    LinkedPersonKnoten neu = _listenkopf.gibNachfolger();
    links.setzeNachfolger(neu);
    ++_anzahlPersonen;
}

Ich weiß nicht was mit links so genau gemeint ist
Das ist der Knoten der sich links von der Position befindet, an welche der neue Knoten eingefügt werden soll.
nehmen wir an wir haben 3 Elementen und zwischen 2 und 3 sollte man ein Neues platzieren !
Einfügeposition wäre in dem Fall Position 3 und "links" davon ist Position 2. Die ehemalige Position 3 wird nach dem Einfügen zu Position 4.


Etwas zum Nachdenken für dich:

Du möchtest das Element doch an einer bestimmten Position einfügen und nicht immer am Anfang, oder?

Erzeugt denn gibNachfolger() einen neuen Knoten?
 
Zuletzt bearbeitet:
Bitte verwende doch zum Einfügen von Code die Code-Tags: Das Symbol </> ganz links im Beitragseditor.
Java:
public void fuegeEin(Person person, int position) {
    if(person == null) return;
    if(!istGueltigeEinfuegePosition(position)) return;

    LinkedPersonKnoten links = _listenkopf ;
    LinkedPersonKnoten neu = _listenkopf.gibNachfolger();
    links.setzeNachfolger(neu);
    ++_anzahlPersonen;
}


Das ist der Knoten der sich links von der Position befindet, an welche der neue Knoten eingefügt werden soll.

Etwas zum Nachdenken für dich:

Du möchtest das Element doch an einer bestimmten Position einfügen und nicht immer am Anfang, oder?

Erzeugt denn gibNachfolger() einen neuen Knoten?
Danke für deine Antwort ! Nein , es wird nur der Nachfolger angezeigt ! Aber wie kann ich das neue Element positionieren ? Es muss von Typ LinkedPersonknoten sein ! position ist von Typ int ! und wenn ich
Java:
LinkedPersonKnoten neu = _listenkopf
schreibe dann wird das am Anfang der Liste platziert?oder ?
 
Aber wie kann ich das neue Element positionieren ?
Es gibt doch eine Methode, die den Knoten an einer bestimmten Stelle liefert: gibKnoten() und wie du einen Knoten "einfügen" kannst, hast du doch selbst in deinem Beitrag #3 beschrieben.

wenn ich
Java:
LinkedPersonKnoten neu = _listenkopf
schreibe dann wird das am Anfang der Liste platziert?oder ?
Es wird kein neuer Knoten erzeugt. Es wird nur der Variablen "neu" die Referenz auf den Kopf der Liste zugewiesen.

Du willst ja einen neuen Knoten einfügen, also musst du auch einen neuen Knoten erzeugen.
 
Zuletzt bearbeitet:
Es gibt doch eine Methode, die den Knoten an einer bestimmten Stelle liefert: gibKnoten() und wie du einen Knoten "einfügen" kannst, hast du doch selbst in deinem Beitrag #3 beschrieben.


Es wird kein neuer Knoten erzeugt. Es wird nur der Variablen "neu" eine Referenz auf den ersten Knoten zugewiesen.

Du willst ja einen neuen Knoten einfügen, also musst du auch einen neuen Knoten erzeug
 
Java:
 public void fuegeEin(Person person, int position)
    {
        if(person == null) return;
        if(!istGueltigeEinfuegePosition(position)) return;

        LinkedPersonKnoten links = gibKnoten(position)  ;
        LinkedPersonKnoten neu = gibKnoten(position)    ;
        links.setzeNachfolger(neu);
        ++_anzahlPersonen;
    }
soll es so aussehen ? Was ist hier mit links genau gemeint ?sollte man auch die position hier bestimmen ?
Java:
 LinkedPersonKnoten links = gibKnoten(position)
 
Was ist hier mit links genau gemeint ?
Steht doch oben:
Das ist der Knoten der sich links von der Position befindet, an welche der neue Knoten eingefügt werden soll.
Lies dir doch deine eigene Beschreibung in #3 durch. Du benötigst doch den Vorgänger, um den neuen Knoten einzufügen.

Die Knoten kann man sich ja einfach hintereinander gereiht vorstellen:

1 2 3 4 5 6 7 ...

Wenn du einen Knoten an Position 5 einfügen möchtest, dann brauchst du den Vorgänger links davon, nämlich Knoten 4.


Hier im Konstruktor der Liste wird beispielsweise ein neuer Knoten erzeugt und dem Kopf der Liste zugewiesen.
Java:
public LinkedPersonListe() {
    _listenkopf = new LinkedPersonKnoten(); // erzeugt einen neuen Knoten mit new
    _anzahlPersonen = 0;
}
 
Steht doch oben:

Lies dir doch deine eigene Beschreibung in #3 durch. Du benötigst doch den Vorgänger, um den neuen Knoten einzufügen.

Die Knoten kann man sich ja einfach hintereinander gereiht vorstellen:

1 2 3 4 5 6 7 ...

Wenn du einen Knoten an Position 5 einfügen möchtest, dann brauchst du den Vorgänger links davon, nämlich Knoten 4.


Hier im Konstruktor der Liste wird beispielsweise ein neuer Knoten erzeugt und dem Kopf der Liste zugewiesen.
Java:
public LinkedPersonListe() {
    _listenkopf = new LinkedPersonKnoten(); // erzeugt einen neuen Knoten mit new
    _anzahlPersonen = 0;
}
Ich verstehe die Logik dahinter! Mir fällt es leider nur schwierig das zu implementieren ! Das bedeutet , dass wir den Vorgänger positionieren müssen nämlich so : mit gibKnoten() und dann muss der Vorgänger auf das Neue zeigen mit "setzeNachfolger" das neue wird "_listenkopf" zugewiesen , das hat noch keine position ! Nur ich habe es nicht verstanden was du mit diesem Satz meinst "ein neuer Knoten erzeugt und dem Kopf der Liste zugewiesen" bedeutet das wir einen neuen Knoten immer am Anfang der Liste zufügen ? soll der Code so aussehen ?Danke für deine Hilfe !
Java:
 public void fuegeEin(Person person, int position)
    {
        if(person == null) return;
        if(!istGueltigeEinfuegePosition(position)) return;

        LinkedPersonKnoten links = gibKnoten(position)  ; //Vorgänger
        LinkedPersonKnoten neu = _listenkopf            ; // neue
        links.setzeNachfolger(neu);
        ++_anzahlPersonen;
    }
 
Ich habe das Gefühl, dass Du da bisher die notwendigen Schritte nicht verstanden hast. Du hast Dir schon mal den Knoten geholt, hinter dem eingefügt werden muss. Aber dann? Was bitte willst Du ab Zeile 7 machen?

Was ist in _listenkopf enthalten?

Das, was Du doch haben willst ist ein neuer Knoten. Wie legst Du einen neuen Knoten an?
Was für Werte kannst Du beim neuen Knoten setzen? Was wird da wie gesetzt?
 
ich habe den Code für Einfügen , Entfernen und leeren nochmals bearbeitet
Java:
public void fuegeEin(Person person, int position)
    {
        if(person == null) return;
        if(!istGueltigeEinfuegePosition(position)) return;

        LinkedPersonKnoten links = gibKnoten(position)  ;
        LinkedPersonKnoten neu =  new LinkedPersonKnoten();
        links.setzeNachfolger(neu);
        ++_anzahlPersonen;
    }

    /**
     * Entferne die Person an der angegebenen Position. Alle folgenden Eintraege
     * werden um eine Position verschoben. Bei einer ungueltigen Position
     * bleibt die Liste unveraendert.
     *
     * @param position Die Position der Person, der entfernt werden soll.
     */
    public void entferne(int position)
    {
        if(!istGueltigePosition(position)) return;
        LinkedPersonKnoten links = gibKnoten(position)  ;
        LinkedPersonKnoten rechts = gibKnoten(position) ;
        links.setzeNachfolger(rechts);
        
        --_anzahlPersonen;
    }

    /**
     * Entferne alle Personen aus der Liste.
     */
    public void leere()
    {
        _listenkopf=null    ;
        _anzahlPersonen = 0;
    }
aber es funktioniert immer noch nicht! Was muss ich noch verbessern ?
 
Was muss ich noch verbessern ?
Du musst einfach das machen, was du oben selbst beschrieben hast:
nehmen wir an wir haben 3 Elementen und zwischen 2 und 3 sollte man ein Neues platzieren ! Da muss Element 2 nicht mehr eine Referenz auf 3 haben sondern auf das Neue Element hinweisen ! Der Nachfolger von 2 wird das Neue Element sein und das neue Element referenziert auf Nummer 3 !
Derzeit setzt du nur einen neuen Nachfolger. Der Nachfolger muss aber auch seinen Nachfolger kennen (Letzter Satz, deiner Beschreibung).

Außerdem enthält der neue Knoten keine "Nutzdaten" (die Person).

Wie würdest du denn das Entfernen beschreiben? Beispiel:

1 2 3 4 5 6 .. Knoten 4 soll entfernt werden. Was musst du tun?
 
Zuletzt bearbeitet:
Also schauen wir uns mal Codeausschnitte an:
Java:
        LinkedPersonKnoten links = gibKnoten(position)  ;
        LinkedPersonKnoten rechts = gibKnoten(position) ;

Was ist da in links bzw. rechts drin?

Spielen wir das einmal gedanklich durch:
Wir haben eine SPielzeugeisenbahn.
Dabei hast Du eine Lok - diese nennen wir einmal _listenkopf.

Nun kannst Du von der Lok aus zu Waggons gehen: Dazu haben wir dann eine Methode: gibWaggon(nr).

Nun hast Du eine Lok mit z.B. 5 Anhängern.

<Lok> -> <W1> -> <W2> -> <W3> -> <W4> -> <W5> ->

gibWaggon(2) gibt einem also den Waggon 2: <W2>
Wenn Du das noch einmal aufrufst, dann bekommmst du wieder <W2>

Nun wollen wir W3 heraus nehmen - wie sieht das dann aus?
<Lok> -> <W1> -> <W2> -> <W4> -> <W5> ->

W2 zeigt also auf das, auf das W3 gezeigt hat.
Um W3 zu löschen, brauchen wir also W2 und W3.

Aber nun ist noch die Frage: Was ist, wenn wir W1 löschen wollen? Ein w0 gibt es ja nicht. Der Ansatz oben funktioniert also schlicht nicht. Da müssen wir uns also überlegen, wie wir da vorgehen können.

Also mein Ratschlag: Spiel etwas mit einer Spielzeugeisenbahn um zu verstehen, wie das mit dem Ankoppeln und Abkoppeln funktioniert. 🙂
 
W2 zeigt also auf das, auf das W3 gezeigt hat.
Um W3 zu löschen, brauchen wir also W2 und W3.
Schöne Analogie!

Nur noch ein Hinweis: Die Lösungsvorgabe im Code, sieht ja sowohl "links" als auch "rechts" vor, was nicht ganz genau zu dem zweiten Satz von Konrads Erklärung passt.

Wenn du W3 löschen willst, dann ist links = W2 und rechts = W4. Nach dem "Löschen" sollte W2 auf W4 zeigen.
 
Aber nun ist noch die Frage: Was ist, wenn wir W1 löschen wollen? Ein w0 gibt es ja nicht. Der Ansatz oben funktioniert also schlicht nicht. Da müssen wir uns also überlegen, wie wir da vorgehen können.
Sollte funktionieren, weil der Vorgänger (links) von W1 (also Position 0) der Lok entspricht (was in gibKnoten() so implementiert ist) und der Nachfolger (rechts) ist ja W2. Nach dem Entfernen muss also die Lok (_listenkopf) auf W2 zeigen.
 
Sollte funktionieren, weil der Vorgänger (links) von W1 (also Position 0) der Lok entspricht (was in gibKnoten() so implementiert ist) und der Nachfolger (rechts) ist ja W2. Nach dem Entfernen muss also die Lok (_listenkopf) auf W2 zeigen.
Ahh gut, dann wird der Sonderfall dort bereits behandelt. So genau hatte ich mir den Code bisher nicht angesehen. Danke für die Korrektur / Ergänzung!
 
Java:
public void fuegeEin(Person person, int position)
    {
        if(person == null) return;
        if(!istGueltigeEinfuegePosition(position)) return;

        LinkedPersonKnoten links = gibKnoten(position)  ;
        LinkedPersonKnoten neu = new LinkedPersonKnoten();
        links.setzeNachfolger(neu);
        ++_anzahlPersonen;
    }
ich bekomme NullPointerException , ich denke , ich muss person als Parameter irgendwie an LinkedPersonKnoten neu zuweisen , aber die sind nicht vom gleichen Typ , weiß ich nicht wie man das macht !
 
Du benützt den falsche Konstruktor. Die Klasse LinkedPersonKnoten bietet Dir noch einen weiteren an, der zwei Parameter annimmt. So steht es zumindest in der Klassenbeschreibung, welche Du in Post #1 angehängt hast.
die Constructors haben den gleichen Namen , habe versucht so schreiben
Java:
LinkedPersonKnoten neu=new LinkedPersonKnoten(person)
aber es hat nicht geklappt !
 
Das ist aber doch problematisch, wenn das letzte Element gelöscht werden soll. Oder habe ich jetzt wieder etwas verpasst / übersehen?
Nö, nichts übersehen, das kann problematisch werden. Die Methode gibt dann null zurück. Da ist dann ggf. noch ein Test fällig.

EDIT: Wobei bei Löschen, wie unten implementiert, nichts passieren dürfte. Es wird einfach null als Nachfolger gesetzt, was ja passen würde.
 
Zuletzt bearbeitet:
Java:
 public void fuegeEin(Person person, int position)
    {
        if(person == null) return;
        if(!istGueltigeEinfuegePosition(position)) return;

        LinkedPersonKnoten links = gibKnoten(position)  ;
        LinkedPersonKnoten neu =  new LinkedPersonKnoten();
        links.setzeNachfolger(neu);
        ++_anzahlPersonen;
    }

    /**
     * Entferne die Person an der angegebenen Position. Alle folgenden Eintraege
     * werden um eine Position verschoben. Bei einer ungueltigen Position
     * bleibt die Liste unveraendert.
     *
     * @param position Die Position der Person, der entfernt werden soll.
     */
    public void entferne(int position)
    {
        if(!istGueltigePosition(position)) return;
        LinkedPersonKnoten links = gibKnoten(position-1);
        LinkedPersonKnoten rechts = gibKnoten(position+1);
        links.setzeNachfolger(rechts);
       
        --_anzahlPersonen;
    }
ich bekomme immer noch solche errors : das Problem liegt in LinkedPersonKnoten neu = new LinkedPersonKnoten(); denke ich , es nimmt auch kein person als parameter , was meint ihr ?
 

Anhänge

  • error1.PNG
    error1.PNG
    17,1 KB · Aufrufe: 0
Ich meine, du solltest die Dokumentation durchlesen, die du hier auch mitgelierfert hast. Es gibt einen Konstruktor für LinkedPersonKnoten, der als Parameter eine Person (die Daten des Knotens) und einen Nachfolger nimmt. Steht doch alles da, auch schon ein paar Beiträge weiter oben, wird das erwähnt.

Und bevor du fragst: Der Nachfolger ist der ursprüngliche Nachfolger, des linken Knotens (Vorgänger). Da gibt es auch eine passende Methode. Auch in der selben Doku.

EDIT: Falls du Schwierigkeiten mit dem Lesen der Doku oder dem Verständnis hast, dann stell hier entsprechende Fragen. Es ist wichtig so eine Doku lesen zu können! Das gehört zum Handwerkszeug.
 
Zuletzt bearbeitet:
Java:
public void fuegeEin(Person person, int position)
    {
        if(person == null) return;
        if(!istGueltigeEinfuegePosition(position)) return;

        LinkedPersonKnoten links = gibKnoten(position)  ;
        LinkedPersonKnoten neu = new LinkedPersonKnoten(person,links.gibNachfolger());
        links.setzeNachfolger(neu);
        ++_anzahlPersonen;
    }
Ich habe als parameter person und links.gibNachfolger gegeben , was muss ich noch beachten damit es funktioniert ?
 

Neue Themen


Zurück
Oben