Zum Inhalt springen

c++/cli verkettete Liste brauche Hilfe


Empfohlene Beiträge

Geschrieben

Hallo Leute,

wie mein Nick schon sagt bin neuling in diesem Thema.

Ich habe eine Aufgabenstellung bekommen bei der ich aus einer einfach verketteten Liste eine doppelt verkettete machen soll.

Als erstes wollte ich in der einfach verketteten Liste nun einen Zeiger einfügen der immer auf das ende der Liste zeigt und über diesen die neuen Werte "inhalt" anfügen.

Doch leider scheitert es schon dabei sehe irgendwie vor lauter Bäume den Wald nicht mehr.

Wer kann mir anhand des Beispiels helfen das ich es endlich richtig verstehe?

Ich weis dass ich einen Zeiger haben muß "ende" der das Listenende nach jedem Einfügen ermittelt und an die Funktion main() zurückliefert

und als Argument beim Einfügen übergebe ich dann das "ende" und nicht mehr den "anfang".

aber wie erstelle ich hier den Zeiger ende das er immer auf das Listenende zeigt



#include "stdafx.h"


using namespace System;


//die Struktur für den verwalteten Heap

ref struct beispiel {

	int inhalt;

	beispiel ^next;


};


void einfuegen(int inhaltneu, beispiel ^anfang) {


	beispiel ^zeiger;

	zeiger=anfang;


	while (zeiger->next!=nullptr) {

		zeiger=zeiger->next;

	}


	zeiger->next=gcnew beispiel;

	zeiger=zeiger->next;

	zeiger->inhalt=inhaltneu;


}

void ausgabe(beispiel ^anfang) {

	beispiel ^zeiger;

	zeiger=anfang;

	Console::WriteLine("{0}", zeiger->inhalt);


	while (zeiger->next != nullptr) {

			zeiger = zeiger->next;

			Console::WriteLine("{0}", zeiger->inhalt);

	}


}


int main(array<System::String ^> ^args)

{


	beispiel ^anfang;


	anfang=gcnew beispiel;

	anfang->inhalt=0;


	for (int schleife=1;schleife<5;schleife++) {

		einfuegen(schleife, anfang);


	}



	ausgabe(anfang);


	return 0;

}


Geschrieben

Hallo,

erst einmal Danke für die schnellen Antworten.

Hmm ich glaube ich habe meine Anfrage etwas falsch formuliert,

das Endziel ist zwar eine doppelt verkettete Liste aber für den Anfang um die Sache etwas besser zu verstehen (hoffe ich) möchte ich die jetzt vorhandene einfache Liste nur etwas "frisieren".

So wie sie im Moment geschrieben ist hangel ich mich ja immer vom Anfang zum Ende durch. Ich möchte jetzt durch das einfügen eines Zeigers auf das Ende erreichen das der "inhalt" über diesen immer gleich an das Ende eigefügt wird.

Das unten verlinkte Tut hatte ich auch schon gefunden und mir eingehend angesehen aber so richtig ist der Groschen (nein muß ja jetzt Cent heißen) nicht gefallen

Geschrieben

Hatte es so versucht unter anderem



#include "stdafx.h"


using namespace System;


//die Struktur für den verwalteten Heap

ref struct beispiel {

	Int32 inhalt;

	beispiel ^next;


};


void einfuegen(Int32 inhaltneu, beispiel ^ende) {



	//ende->next=ende;

	ende->next=gcnew beispiel;

	ende=ende->next;

	ende->inhalt=inhaltneu;




}

void ausgabe(beispiel ^anfang) {

	beispiel ^zeiger;

	zeiger=anfang;

	Console::WriteLine("{0}", zeiger->inhalt);


	while (zeiger->next != nullptr) {

			zeiger = zeiger->next;

			Console::WriteLine("{0}", zeiger->inhalt);

	}


}


int main(array<System::String ^> ^args)

{



	beispiel ^ende;

	beispiel ^anfang;


	anfang=gcnew beispiel;

	anfang->inhalt=0;

	ende=anfang;


	for (Int32 schleife=1;schleife<5;schleife++) {

		einfuegen(schleife, ende);


	}



	ausgabe(anfang);


	return 0;

}


aber da kommt nur als Ausgabe

0

4

Also keine Liste mehr :(

Geschrieben

Wie weit bist Du mit Deiner Liste?

Helfe Dir da aufs Pferd. :upps

Ich vermisse in Deiner ref struct das Handle auf den vorigen Datensatz.

Die ref struct kann so nur eine einfach verkette Liste aufnehmen.

ref struct listenelement

{

	String^ daten;


	listenelement^ next;


	listenelement^ previous;//Speichert die Vorgängeradresse


};

Gruß René

Geschrieben

Hallo RB,

erst einmal Danke für deine Antwort.

Also das ist der Stand der Dinge.

Die erste List oben ist ja eine einfache liste in der ich mich mit dem zeiger immer vom Anfang bis zum Ende der List durch hangel um ein neues Element anzuhängen.

In der zweiten List wollte ich dann einen Zeiger setzen der immer auf das Ende der Liste zeigt und ich das nächste Element durch ihn immer direkt ans Ende hängen kann. Das habe ich mittlerweile auch endlich geschafft.

jetzt möchte ich die erste List zu einer doppelt verketteten machen die ich durch eine Funktion vorwärts und durch eine weitere Funktion rückwärts ausgeben kann.

In meiner ref struct das Handle auf den vorigen Datensatz habe ich auch schon gesetzt

aber wie ich dann den zeiger previous in der Funktion einfuegen genau verwende da bin ich noch etwas am grübeln und wie ich die funktion ausgabe rueckwaerts aufbauen muß auch

kann das überhaupt gehen mit der ersten List oder brauche ich dafür doch die zweite mit dem zeiger ende:confused:

Geschrieben

Hallo Neuling 5

Ein Handle (Zeiger) das auf das Ende zeigt brauchst Du in diesem Sinne nicht.

Da ja das Ende der Liste schon im Handle ->next gespeichert ist.

Die Ausgabe ist in diesem Sinne auch recht einfach.

Du brauchst nur eine Schleife die vom Ende der Liste zum ->previous geht, bis previous = nullptr hat.

Das was sehr wichtig ist...

In der Funktion Einfügen, musst Du den previous zuvor speichern dann erst einen neuen Datensatz mit gcnew anlegen und danach den previous im neuen Datensatz speichern.

Solltest Du das nicht machen, hast Du einen previous der immer auf sich selber zeigt.

Das ist in Deiner Ausgabe gut zusehen.

Dann spricht man von einer Rekursion.

Gruß René

Geschrieben

Also irgendwie drehe ich mich immer im Kreis und komme kein Stück weiter,

deshalb werde ich das Thema verkettete Listen erst einmal auf Eis legen und mich später noch einmal damit beschäftigen.:(

Aber trotzdem Danke an alle die sich die Mühe gegeben haben mir zu helfen.

Geschrieben

Hallo Neuling5

Komm lass uns das Ding jetzt Durchziehen.

Glaub mir das ist nicht so schwer.

Ich gebe Dir jetzt die Funktion einfügen.

Das ist echt nicht schwer, wenn man in die richtige Richtung denkt.

//neues Element am Ende der Liste einfügen

void einfuegen(String^ datenneu, listenelement^ listenanfang)

{

	//ein Hilfshandle zum Wandern in der Liste


	listenelement^ hilfsHandle = listenanfang;


	//ein Hilfshandle zum speichern der vorgänger Adresse


	listenelement^ previousAddress;


	//Durch die Liste gehen, bis das letzte Element erreicht ist


	while (hilfsHandle->next != nullptr)

	{

		hilfsHandle = hilfsHandle->next;


	}


	//die Aktuelle Adresse im Hilfshandle zwischenspeichern


	previousAddress = hilfsHandle; 


	//neues Element erstellen


	hilfsHandle->next = gcnew listenelement;


	//Hilfshandel auf das neue Element setzen


	hilfsHandle = hilfsHandle->next;


	//Die vorgängeradresse im neuen Handle speichern


	hilfsHandle->previous = previousAddress;


	//Zeichenkette im neuen Element eintragen


	hilfsHandle->daten = datenneu;


	//nullptr wird automatisch zugewiesen!


}

Wir können den Code gerne durchgehen, dass ist wichtig damit Du weißt was da passiert.

Gruß René

  • 2 Jahre später...
Geschrieben

hallo, ich habe ebenfalls Probleme, die verkettete Liste von oben nachzuvollziehen. Ich habe schon einige Lösungsansätze gefunden,jedoch mehrere ! Jetzt weiss ich immer noch nicht, wie diese Liste funktioniert.

ich habe hier nochmals das Listing und MEINE Interpretation der einzelnen Stationen in grüner Farbe dargestellt. Vielleicht wäre jemand so nett, und kann meine Interpretation nachprüfen und ggf. mit roter Farbe korrigieren. Danke http://forum.fachinformatiker.de/images/smilies/roll.gif

#include "stdafx.h"

using namespace System;

//die Struktur für den verwalteten Heap

ref struct beispiel {

int inhalt;

beispiel ^next;

hier wird eine Struktur angelegt. Die Struktur enthält ein Feld inhalt und einen weiteren Zeiger oder Handle welcher wiederum auf inhalt eines weiteren Speichers zugreifen bzw. zeigen kann.

};

void einfuegen(int inhaltneu, beispiel ^anfang) {

unter int inhaltneu wird jetzt 1 aus main übergeben und unter beispiel ^anfang anfang von main. Kann mir jemand sagen, was genau jetzt in dieser Funktion einfuegen in klammern stehen würde ? Wird durch die Übergabe der Parameter an diese Funktion bereits ein Wert in der Struktur gespeichert ?

beispiel ^zeiger;

zeiger=anfang;

hier wird nun ein weiterer Handle zeiger erstellt und auf listenanfang gesetzt. zeigt dieser zeiger Handle jetzt auf 0 oder auf 0 + next oder auf 1 und next ?

while (zeiger->next!=nullptr) {

zeiger=zeiger->next;

}

Liste durchgehen, bis zeiger.next ungleich null ist. Dann wird dieser Zeiger auf next gesetzt.

zeiger->next=gcnew beispiel;

wieder Speicher reservieren

zeiger=zeiger->next;

zeiger wird nochmals auf next gesetzt ? welches next ist das denn jetzt ? das von zeiger oder von anfang oder der struktur selbst ?

zeiger->inhalt=inhaltneu;

das ist wieder klar

}

void ausgabe(beispiel ^anfang) {

beispiel ^zeiger;

zeiger=anfang;

Console::WriteLine("{0}", zeiger->inhalt);

while (zeiger->next != nullptr) {

zeiger = zeiger->next;

Console::WriteLine("{0}", zeiger->inhalt);

}

}diese Funktion ist auch wieder klar !

int main(array<System::String ^> ^args)

{

beispiel ^anfang;

hier wird ein Handle bzw. Zeiger anfang erstellt, welcher die Daten der Struktur (also inhalt und next) speichern kann

anfang=gcnew beispiel;

hier wird für den Handle speicher reserviert

anfang->inhalt=0;

das erste Element wird in den handle anfang geschrieben. Da ja der Handle indirekt mit der Struktur beispiel arbeitet, wird hier jetzt indirekt dieser Wert in die Struktur geschrieben oder in anfang selbst ?

for (int schleife=1;schleife<5;schleife++) {

einfuegen(schleife, anfang);

in dieser schleife wird das nächste element und anfang an die funktion einfuegen übergeben. Was wird denn hier genau mit anfang übergeben ?

}

ausgabe(anfang);

das ist klar !

return 0;

}

DANKE !!!

Geschrieben

#include "stdafx.h"


using namespace System;


//die Struktur für den verwalteten Heap

ref struct beispiel {

	int inhalt;

	beispiel ^next;


[COLOR="Green"]hier wird eine Struktur angelegt. Die Struktur enthält ein Feld inhalt und einen weiteren Zeiger oder Handle welcher wiederum auf inhalt eines weiteren Speichers zugreifen bzw. zeigen kann.[/COLOR]


};


void einfuegen(int inhaltneu, beispiel ^anfang) {


[COLOR="Green"]unter int inhaltneu wird jetzt 1 aus main übergeben und unter beispiel ^anfang   anfang von main. Kann mir jemand sagen, was genau jetzt in dieser Funktion einfuegen in klammern stehen würde ? Wird durch die Übergabe der Parameter an diese Funktion bereits ein Wert in der Struktur gespeichert ?[/COLOR]

[COLOR="Red"]Falsch. Die Funktion wird mehrmals aufgerufen.

Paramater: 1, anfang (aus main)

Paramater: 2, anfang (aus main)

Paramater: 3, anfang (aus main)

Paramater: 4, anfang (aus main)

[/COLOR]


	beispiel ^zeiger;

	zeiger=anfang;


[COLOR="Green"]hier wird nun ein weiterer Handle zeiger erstellt und auf listenanfang gesetzt. zeigt dieser zeiger Handle jetzt auf 0 oder auf 0 + next oder auf 1 und next ?[/COLOR]

[COLOR="Red"]

Auf anfang (aus main); folglich 0.

[/COLOR]


	while (zeiger->next!=nullptr) {

		zeiger=zeiger->next;

	}


[COLOR="Green"]Liste durchgehen, bis zeiger.next ungleich null ist. Dann wird dieser Zeiger auf next gesetzt. [/COLOR]


	zeiger->next=gcnew beispiel;

[COLOR="Green"]wieder Speicher reservieren[/COLOR]

	zeiger=zeiger->next;

[COLOR="Green"]zeiger wird nochmals auf next gesetzt ? welches next ist das denn jetzt ? das von zeiger  oder von anfang oder der struktur selbst ?[/COLOR]

[COLOR="Red"]zeiger->next ist zu dem Zeitpunkt = gcnew beispiel (neues object)[/COLOR]

	zeiger->inhalt=inhaltneu;

[COLOR="Green"]das ist wieder klar[/COLOR]


}

void ausgabe(beispiel ^anfang) {

	beispiel ^zeiger;

	zeiger=anfang;

	Console::WriteLine("{0}", zeiger->inhalt);


	while (zeiger->next != nullptr) {

			zeiger = zeiger->next;

			Console::WriteLine("{0}", zeiger->inhalt);

	}


}[COLOR="Green"]diese Funktion ist auch wieder klar ![/COLOR]


int main(array<System::String ^> ^args)

{


	beispiel ^anfang;


[COLOR="Green"]hier wird ein Handle bzw. Zeiger anfang erstellt, welcher die Daten der Struktur (also inhalt und next) speichern kann[/COLOR]


	anfang=gcnew beispiel;

[COLOR="Green"]hier wird für den Handle speicher reserviert[/COLOR]


	anfang->inhalt=0;

[COLOR="Green"]das erste Element wird in den handle anfang geschrieben. Da ja der Handle indirekt mit der Struktur beispiel arbeitet, wird hier jetzt indirekt dieser Wert in die Struktur geschrieben oder in anfang selbst ?[/COLOR]


	for (int schleife=1;schleife<5;schleife++) {

		einfuegen(schleife, anfang);


[COLOR="Green"]in dieser schleife wird das nächste element und anfang an die funktion einfuegen übergeben. Was wird denn hier genau mit anfang übergeben ?[/COLOR]

[COLOR="Red"]Das weiter oben definierte Objekt anfang (erstes Element in der Liste)[/COLOR]


	}



	ausgabe(anfang);

[COLOR="Green"]das ist klar ![/COLOR]


	return 0;

}


Geschrieben

ich fass nochmals zusammen. Ich starte bei main():

zu listenelement ^listenanfang

ein lokaler Handle listenanfang wird auf die Struktur gesetzt, also:

listenanfang ---> daten:

next:

dann wird Speicher reserviert und listenanfang zugewiesen (mit gcnew)

dann wird in listenanfang Element 0 eingefügt, also:

listenanfang ---> Element 0

next: nullptr.

dann wird an Funktion einfuegen übergeben: Element 1 und listenanfang

also:

listenanfang ----> Element 0

next: -------> Element__ (Bei Funktionsende dann 1)

next: nullptr.

unter einfuegen()

ein lokaler hilfshandle für die Struktur wird erstellt. Hilfshandle wird auf listenanfang gesetzt (erstes Element), also:

listenanfang ---> Element 0

hilfshandle ------> next: ------> Element__ (bei Funktionsende dann 1)

next: nullptr.

while Schleife ist klar.

hilfshandle = hilfshandle->next;

also: hilfshandle ---> Element__ (bei Funktionsende dann 1)

next: nullptr.

Speicher reservieren und hilfshandle zuweisen

dann nochmals hilfshandle=hilfshandle->next

also hilfshandle direkt auf das next setzen

daten werden nun eintragen, also:

listenanfang -> Element 0

next: ---> Element 1

next: nullptr. <---hilfsHandle

Ende des ersten Einfügens.

Lieg ich noch richtig ?

Geschrieben

listenanfang -> Element 0

next: ---> Element 1

next: nullptr. <---hilfsHandle

Ende des ersten Einfügens.

Lieg ich noch richtig ?

Meinst du HilfsHandle ist NULL oder (HilfsHandle - Next) == NULL? (Der Pfeil nach links irritiert etwas :beagolisc)

Wenn du letzteres meinst, dann ist es richtig.

listenanfang


  • inhalt = 0
  • next =

    • inhalt = 1
    • next = NULL

    (= HilfsHandle)

Geschrieben

wenn du vielleicht Lust und Zeit hast, könntest du mir deine Vorstellungsweise darbieten ? ich scheitere mittlerweile schon an den kleinsten Dingen, wie z.B. was am Anfang in der Funktion einfuegen() überhaupt drinnensteht und ob dies schon Auswirkungen auf irgendwas hat

Geschrieben
wenn du vielleicht Lust und Zeit hast, könntest du mir deine Vorstellungsweise darbieten ?

Ich spiel mal Debugger...:

Start Main()

Erstelle Zeiger A auf ein object.

Erstelle neues Object, reserviere speicher und weise Addresse A zu.

inhalt = 0

next = NULL

Schreibe in A-> Inhalt 0.

Beginne Schleife

Wert = 0

Start einfuegen.

Parameter inhaltneu = 1

Parameter anfang = A

Erstelle Zeiger tmp auf ein object.

Weise tmp = A zu.

Überprüfe tmp -> next. (= A -> next)

tmp -> next == NULL. Überspringe Schleife.

Erstelle neues Object B, reserviere speicher und weise Addresse A->Next zu.

inhalt = 0

next =

Weise tmp B zu.

inhalt = 0

next = NULL

Setze tmp -> inhalt auf inhaltneu

inhalt = 0

next =

Erhöhe Wert um 1.

Wert = 2.

Prüfe Wert < 5.

Start einfuegen.

Parameter inhaltneu = 2

Parameter anfang = A

Erstelle Zeiger tmp auf ein object.

Weise tmp = A zu.

Überprüfe tmp -> next. (= A -> next)

Weise tmp A -> next zu.

Überprüfe tmp -> next. (= B -> next)

tmp -> next == NULL. Breche ab.

Erstelle neues Object C, reserviere speicher und weise Addresse B->Next zu.

inhalt = 0

next =

Weise tmp C zu.

inhalt = 0

next = NULL

Setze tmp -> inhalt auf inhaltneu

inhalt = 0

next =

Wiederhole //Schreibfaul.

Ende Schleife

Gebe alle Elemente aus.

Ende Main

Reicht?

  • 3 Wochen später...
Geschrieben

hallo zusammen ! ich habe selbst mal versucht die Aufgabe zu lösen. die Aufgaben waren ja, bei der einfach verketteten Liste diese so neu zu gestalten, dass ein listenende erstellt wird in einem eigenen handle. Das Listenende soll nach jedem Einfügen ermittelt und an die Main Funktion zurückgegeben werden. Als Argument soll man beim Einfügen nicht den listenanfang sondern listenende übergeben.

Könnt ihr mal schauen, ob meins semantisch korrekt ist ? :

#include "stdafx.h"

using namespace System;

ref struct listenelement {

String ^daten;

listenelement ^next;

};

listenelement ^einfuegen (String ^neu, listenelement ^listenende) {

listenelement ^hilfshandle;

hilfshandle=listenende;

while (hilfshandle->next != nullptr)

hilfshandle=hilfshandle->next;

hilfshandle->next = gcnew listenelement;

hilfshandle = hilfshandle->next;

hilfshandle->daten=neu;

return hilfshandle;

}

void ausgeben(listenelement ^listenanfang) {

listenelement ^hilfshandle;

hilfshandle = listenanfang;

Console::WriteLine("erstes Element: {0}",hilfshandle->daten);

while (hilfshandle->next != nullptr) {

hilfshandle = hilfshandle->next;

Console::WriteLine("nächstes Element: {0}",hilfshandle->daten);

}

}

int main(array<System::String ^> ^args)

{

listenelement ^listenanfang;

listenanfang = gcnew listenelement;

listenanfang->daten="Element 0";

listenelement ^listenende;

listenende = listenanfang;

while (listenende->next != nullptr)

listenende = listenende->next;

listenende->next = gcnew listenelement;

listenende = listenende->next;

for (Int32 schleife=1;schleife<3;schleife++)

einfuegen("Element "+schleife,listenende);

ausgeben(listenanfang);

return 0;

}

DANKE

Geschrieben

Moin jugiii,

das Listenende übergibst Du ja nach jedem einfügen an die main().

Aber Du übergibst noch immer den Listenanfang als Argument beim einfügen.

Und gesht somit durch die ganze Liste, bis hilfsHandle->next != nullptr ist.

In next steht der letzte Eintrag, nur so als Tipp.

Gruß, René

Geschrieben

ref struct listenelement {

String ^daten;

listenelement ^next;

};

listenelement ^einfuegen(String ^datenneu, listenelement ^listenende) {

listenelement ^hilfsHandle;

hilfsHandle = listenende;

hilfsHandle->next = gcnew listenelement;

hilfsHandle = hilfsHandle->next;

hilfsHandle->daten=datenneu;

return hilfsHandle;

}

void ausgeben(listenelement ^listenanfang) {

listenelement ^hilfsHandle;

hilfsHandle = listenanfang;

Console::WriteLine("{0}",hilfsHandle->daten);

while (hilfsHandle->next != nullptr) {

hilfsHandle = hilfsHandle->next;

Console::WriteLine("{0}",hilfsHandle->daten) ;

}

}

int main(array<System::String ^> ^args)

{

listenelement ^listenanfang;

listenelement ^listenende;

listenanfang = gcnew listenelement;

listenanfang->daten="Element 0";

listenende=listenanfang;

if (listenende->next == nullptr) {

for (Int32 schleife=0;schleife<3;schleife++)

listenende->next = einfuegen("Element "+schleife,listenende);

}

ausgeben(listenanfang);

return 0;

}

jetzt korrekt ?

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...