C++ / CPP ->Einfach verkettete Liste aufbauen und bearbeiten, wie?


12.02.2021, 13:25

Hier ist ein weiterer Ansatz...

1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet

Also. Das Konzept einer verketteten Liste ist eigentlich sehr einfach. Jedes Listenelement (in Deinem Fall die Klasse ListElement) hat einen Zeiger auf Nutzdaten (das kann irgendwas sein) und einen Zeiger auf das nächste Listenelement. Beim letzten Listenelement ist der null als Kennzeichen, dass die Liste fertig ist.

Die Klasse ListElement hat bereits alles implementiert, was Du für das Aufbauen einer verketteten Liste benötigst. Du kannst die nun verwenden. Nachteil an einfach verketteten Listen ist: Du darfst niemals das Startelement verlieren.

Beispiel:

ListElement* liste = new ListElement(NULL); // Das IST die Liste.

Neues Element anfügen? Kein Problem: Du musst nur die ganze Liste durchlaufen und das letzte Element suchen:

ListElement* lastElement = liste;
while (lastElement.getNext() != NULL)
  lastElement = lastElement->getNext();
ListElement* neuesElement = new ListElement(NULL); // Auch hier keine Daten
lastElement->setNext(neuesElement);

Neues Element am Anfang einfügen? Auch kein Problem

ListElement* neuesElement = new ListElement(NULL);
neuesElement->setNext(liste);
liste = neuesElement;

Natürlich kannst Du alle Operationen nochmal in einer Klasse wrappen, wie in dem zweiten Screenshot. Wichtig ist, dass Du innerhalb der Klasse immer den Zeiger auf das erste Element der Liste speicherst. Du brauchst also ein private-Member vom Typ ListElement*, welches diesen Anfang speichert und ggf. im Konstruktor auf das übergebene Element gesetzt wird.

Niklas136 
Fragesteller
 12.02.2021, 13:48
#include <iostream>
#include <string>

class ListElement
{

public:
    ListElement(T* d)
    {
        next = NULL;
        data = d;
    }

    T* getData(void) {return data;}
    void setNext(ListElement* n) {next = n;}
    ListElement* getNext(void) {return next;}

private:
    T* data;
    ListElement* next;
};


int main()
{

ListElement* liste = new ListElement(NULL);

ListElement* lastElement = liste;
while(lastElement->getNext() != NULL)
    lastElement = lastElement->getNext();

ListElement* neuesElement = new ListElement(NULL);
lastElement->setNext(neuesElement);

}
0
ohwehohach  12.02.2021, 13:52
@Niklas136

Der Code erzeugt eine Liste (erstes Element), hängt dann ein zweites Element an und beendet sich dann. Soweit so gut.

1
Niklas136 
Fragesteller
 12.02.2021, 13:54
@ohwehohach

Das wäre schon erstmal wunderbar.. ich bekomme jedoch das Problem: 'T' does not name a type

ListWork.cpp:8:15: error: expected ')' before '*' token
    8 |  ListElement(T* d)
      |             ~ ^
      |               )
ListWork.cpp:14:2: error: 'T' does not name a type
   14 |  T* getData(void) {return data;}
      |  ^
ListWork.cpp:19:2: error: 'T' does not name a type
   19 |  T* data;
      |  ^
ListWork.cpp: In function 'int main()':
ListWork.cpp:27:42: error: no matching function for call to 'ListElement::ListElement(NULL)'
   27 | ListElement* liste = new ListElement(NULL);
      |                                          ^
ListWork.cpp:4:7: note: candidate: 'ListElement::ListElement()'
    4 | class ListElement
      |       ^~~~~~~~~~~
ListWork.cpp:4:7: note:   candidate expects 0 arguments, 1 provided
ListWork.cpp:4:7: note: candidate: 'constexpr ListElement::ListElement(const ListElement&)'
ListWork.cpp:4:7: note:   no known conversion for argument 1 from 'int' to 'const ListElement&'
ListWork.cpp:4:7: note: candidate: 'constexpr ListElement::ListElement(ListElement&&)'
ListWork.cpp:4:7: note:   no known conversion for argument 1 from 'int' to 'ListElement&&'
ListWork.cpp:33:49: error: no matching function for call to 'ListElement::ListElement(NULL)'
   33 | ListElement* neuesElement = new ListElement(NULL);
      |                                                 ^
ListWork.cpp:4:7: note: candidate: 'ListElement::ListElement()'
    4 | class ListElement
      |       ^~~~~~~~~~~
ListWork.cpp:4:7: note:   candidate expects 0 arguments, 1 provided
ListWork.cpp:4:7: note: candidate: 'constexpr ListElement::ListElement(const ListElement&)'
ListWork.cpp:4:7: note:   no known conversion for argument 1 from 'int' to 'const ListElement&'
ListWork.cpp:4:7: note: candidate: 'constexpr ListElement::ListElement(ListElement&&)'
ListWork.cpp:4:7: note:   no known conversion for argument 1 from 'int' to 'ListElement&&'
0
ohwehohach  12.02.2021, 13:57
@Niklas136

Ja. Das liegt daran, dass es den Typ T nicht gibt. Vermutlich willst Du eine generische Liste machen. Da fehlt aber dann noch eine Zeile wie

template<class T>

oder so, damit der Compiler weiß, dass T irgendeine Klasse sein muss.

1
Niklas136 
Fragesteller
 12.02.2021, 14:08
@ohwehohach

Durch ein

class T {};

über dem class ListElement wurde das Programm fehlerfrei ausgeführt. Jetzt muss ich mal eine Funktion schreiben, die mir die Liste ausgibt, um dann weitere Funktionen zu bauen, durch die ich die Liste weiter bearbeiten kann. Ist alles gut?

Auf jeden Fall schonmal vielen Dank im Voraus! :)

0
ohwehohach  12.02.2021, 14:10
@Niklas136

Ja, alles ist gut :-) Du musst halt irgendwas in der Liste speichern was Du auch ausgeben kannst. Aktuell speicherst Du ja keine Daten (Pointer auf Daten ist immer NULL).

Aber das Ausgeben ansich funktioniert genau wie das hinten anhängen. Vorne anfangen, Ausgeben, nächstes Element nehmen, wenn es nicht null ist, usw.

1
Niklas136 
Fragesteller
 12.02.2021, 15:00
@ohwehohach

Ich bekomm es irgendwie nicht hin, anstelle von NULL dem Objekt irgendein Datenwert zuzuweisen. Meistens heißt es: Der Datenwert, dem ich dem Objekt mitgebe kann nicht zu 'T*' konvertiert werden.

0
ohwehohach  12.02.2021, 15:06
@Niklas136

Naja, weil du T als Klasse deklariert hast, musst du auch Instanzen von T übergeben. Wenn Du ein Generic verwenden willst, dann musst du mal googeln. Dafür reicht mein auswendig gewusstes C++ nicht 😂

0