neuling5 Geschrieben 23. Mai 2007 Geschrieben 23. Mai 2007 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; } Zitieren
Guybrush Threepwood Geschrieben 23. Mai 2007 Geschrieben 23. Mai 2007 Nein, du brauchst keinen Zeiger der auf das Ende deiner Liste zeigt sondern jedes Element deiner List benötigt einen Zeiger auf das nächste und das vorherige Element. Zitieren
carstenj Geschrieben 23. Mai 2007 Geschrieben 23. Mai 2007 Hi, ist zwar C, aber sollte dir trotzdem weiterhelfen: C von A bis Z : Doppelt verkettete Listen Zitieren
neuling5 Geschrieben 23. Mai 2007 Autor Geschrieben 23. Mai 2007 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 Zitieren
neuling5 Geschrieben 23. Mai 2007 Autor Geschrieben 23. Mai 2007 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 Zitieren
RB-Softarticle Geschrieben 25. Mai 2007 Geschrieben 25. Mai 2007 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é Zitieren
neuling5 Geschrieben 25. Mai 2007 Autor Geschrieben 25. Mai 2007 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: Zitieren
RB-Softarticle Geschrieben 26. Mai 2007 Geschrieben 26. Mai 2007 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é Zitieren
neuling5 Geschrieben 26. Mai 2007 Autor Geschrieben 26. Mai 2007 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. Zitieren
RB-Softarticle Geschrieben 26. Mai 2007 Geschrieben 26. Mai 2007 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é Zitieren
jugiii Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 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 !!! Zitieren
TDM Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 #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; } Zitieren
jugiii Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 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 ? Zitieren
TDM Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 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 = 0next = inhalt = 1next = NULL (= HilfsHandle) Zitieren
jugiii Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 ich meine damit, dass der Hilfshandle auf dieses next:nullptr gesetzt ist. also hilfshandle zeigt auf das letzte next-Objekt, welches den Wert 0 hat Zitieren
jugiii Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 also mit den langen pfeilen -----> versuche ich immer darzustellen, worauf der handle gerade noch zeigt Zitieren
jugiii Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 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 Zitieren
TDM Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 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? Zitieren
jugiii Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 nicht schlecht, danke. dann ist deins ja wie meins http://forum.fachinformatiker.de/smilies/1012.gif Zitieren
jugiii Geschrieben 28. Mai 2009 Geschrieben 28. Mai 2009 ich habs trotzdem nicht kapiert. ich bräuchte es echt zeile für zeile für Blödies **heul*** Zitieren
jugiii Geschrieben 14. Juni 2009 Geschrieben 14. Juni 2009 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 Zitieren
RB-Softarticle Geschrieben 14. Juni 2009 Geschrieben 14. Juni 2009 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é Zitieren
jugiii Geschrieben 14. Juni 2009 Geschrieben 14. Juni 2009 stimmt. muss ich dann nochmals überarbeiten Zitieren
jugiii Geschrieben 15. Juni 2009 Geschrieben 15. Juni 2009 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 ? Zitieren
Empfohlene Beiträge
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.