C++ Verkettete Liste rückwärts ausgeben.

Vielen Dank für die Antworten.

Ja, ich mach leider ab und zu kleine Fehler wegen dennen danach nichts mehr funktioniert.

Wegen dem Code:

void listenelement::ausgaberueckwaerts()
{
if(next != NULL) {
next->ausgaberueckwaerts();
}
cout << next->daten << 'n';
}

Woher weiß eigentlich das Programm, dass es dann am Ende der Liste anfangen soll?
Und, dass es rückwärts und nicht vorwärts ausgeben soll?

Ich kanns immernoch nicht ganz nachvollziehen, deswegen versuchte ich es mit den Schleifen.


MfG

V.S.
 
Woher weiß eigentlich das Programm, dass es dann am Ende der Liste anfangen soll?
Und, dass es rückwärts und nicht vorwärts ausgeben soll?

Ich kanns immernoch nicht ganz nachvollziehen, deswegen versuchte ich es mit den Schleifen.

Das finde ich super, eine konkrete Frage :), ich hoffe nach diesem Beitrag wirst du das verstehen.

Benutze aber wenn du Code postest die Tasks dafür, da es sonst nicht ganz leicht den Wirrwar zu lesen (auch wenn es in diesem Fall, bei so wenig Code, noch ganz gut geht ;))


Ich werde versuchen dir das zu erklären.

Hier nochmals der Quelltext:

C++:
 void listenelement::ausgaberueckwaerts() 
{
    if(next != NULL) {
        next->ausgaberueckwaerts();
    }
    cout << next->daten << 'n';
}
Die if-Abfrage prüft ob next ungleich NULL ist, solange ein nachfolgendes Objekt vorhanden ist, ist next ungleich NULL. Wenn next also nicht NULL ist dann wird die Funktion ausgaberueckwaets() nochmals aufgerufen, diesmal aber von dem jetzigen next und damit bist du in der nächsten Ebene in der genau das gleiche überprüft wird.

Da bis jetzt aber die Funktion immer wieder neu aufgerufen wurde, ist die Anweisung "cout" noch nicht aufgeführt worden sondern befindet sich in einer "Pause" und wartet bis die vorherigen Anweisung abgearbeitet werden. (die sich aber im Moment in einer anderen Ebene sind)

Wenn next gleich NULL ist heißt es das es keine Nachfolgende Ebene gibt. Dann wird die if-Abfrage übersprungen und es wir durch cout der Inhalt der Variable daten ausgegeben, aber da wir uns nun in der letzten Ebene befinden werden die Daten auch vom letzten Element ausgegeben.

Die Funktion des letzten Elements wird beendet und damit geht es im vorherigen Element mit der Anweisung nach dem if weiter.

So bekommst du den effekt, das die liste rückwärts ausgegeben wird.
________________________________________

Ich habe hier noch ein kleines Beispiel als Grafik: http://img108.imageshack.us/img108/8359/rekursivmu9.png

(Die Fett-markierte Buchstaben sind die "Anweisungen" die noch nicht ausgeführt wurden, sondern warten bis das übergeordnete Element ihre Arbeit erfühlt hat)

jedes Mal wird durch die if-Abfrage geprüft ob next != NULL ist, solange das zutrifft wird die Methode/Funktion des nächsten Elements aufgerufen und da wir wieder getestet etc., und das solange bist next == NULL ist und das ist es erst wenn es kein nachfolgendes Element gibt.

Dann wird die Cout-Anweisung ausgeführt da die Bedingung in der Abfrage nicht mehr zutrifft.

Jetzt wird der Inhalt des letzten Elements ausgegeben:

Nach der Ausgabeanweisung ist die Funktion zu ende, das kann man ja auch an den Quelltext oben sehen. Mit dem Ende der Funktion, kehren wir wieder an die Position des vorherigen Elements und da geht es dann weiter. (wir haben die Funktion rekursiv aufgerufen) Danach steht die Anweisung die Daten des Elements auszugeben. In diesem Element wird
ausgegeben.

Da auch diese Funktion zu ende ist, kehren wir zu dem letzten Element (der letzten Ebene) zurück und setzten auch dort fort. Die Ausgabe-Anweisung wird auch hier ausgeführt.

Jetzt steht auf dem Monitor

Damit funktioniert der rekursiver Aufruf in diesem Fall so, zuerst geht man an das ende der Liste, dann fängt man von da aus an die daten auszugeben, dabei geht man immer eine Position in der liste zurück.

Es tut mir Leid wenn ich viel um den heißen Brei herum geredet habe, aber mir fällt das erklären nicht leicht. (das verstehen schon).

Ich hoffe das du das hier wenigstens etwas nach vollziehen kannst.

Gruß
Rudolf Grauberger
 
Vielen Dank für die Antwort!

ich fange an das Ganze langsam zu kopieren.
(die Erklärung ist übrigens ganz gut)


MfG

V.S.
 
hi ! könnte mir jemand sagen, wie nun das komplette Listing aussehen könnte ? Mein Versuch ist hier unten angegeben, leider stürzt das Programm dann jedesmal ab :(


#include "stdafx.h"

using namespace System;

ref class listenelement {
String ^daten;
listenelement ^next;
public:
void datenSetzen(String ^datenneu);
void einfuegen(String ^datenneu);
void rueckwaerts();
void ausgeben();
};

//die Zeichenkette in das Element schreiben
void listenelement::datenSetzen(String ^datenneu) {
daten=datenneu;
}

//neues Element am Ende der Liste einfügen
void listenelement::einfuegen(String ^datenneu) {
//hat next den Wert nullptr?
//dann ein neues Element einfügen
if (next == nullptr) {
next = gcnew listenelement;
next->daten=datenneu;
//nullptr wird automatisch zugewiesen!
}
//sonst die Methode für next noch einmal aufrufen
else
next->einfuegen(datenneu);
//nur zur Veranschaulichung
Console::WriteLine("Daten {0} wurden eingefügt.",datenneu);
}
void listenelement::rueckwaerts() {

if(next != nullptr){
next->rueckwaerts();
}
Console::WriteLine("{0}", next->daten);
}

//Alle Elemente der Liste ausgeben
void listenelement::ausgeben() {

//den ersten Eintrag ausgeben
Console::WriteLine("{0}",daten);
//wenn das Ende nicht erreicht ist, die Methode für next erneut aufrufen
if (next != nullptr){
next->ausgeben();
}
rueckwaerts();

}

int main(array<System::String ^> ^args)
{
//Handle auf den Anfang der Liste
listenelement ^liste;

//das erste Element per Hand erzeugen
liste = gcnew listenelement;
//Zeichenkette in das erste Element schreiben
liste->datenSetzen("Element 0");

//in einer Schleife mehrere Elemente einfügen
for (Int32 schleife=1;schleife<3;schleife++)
liste->einfuegen("Element "+schleife);

//die Liste ausgeben
liste->ausgeben();

return 0;
}
 
Moin,

zuerst: benutze hier bitte Code-Tags (der '#'-Button im Editor oder klammere den Code mit [_CODE_] ... [_/CODE_] (OHNE die Unterstriche ! ! !). So wie Du es gepostet hast, ist es ziemlich unleserlich!

Und dann wären ein paar weitere Angaben nett:
An welcher Stelle genau stützt Dein Programm denn ab?
Mit welcher Meldung?
Und schreib auch gleich mal dabei, mit welchen System Du programmierst....

Gruß
Klaus
 
"Nach der Ausgabeanweisung ist die Funktion zu ende, das kann man ja auch an den Quelltext oben sehen. Mit dem Ende der Funktion, kehren wir wieder an die Position des vorherigen Elements und da geht es dann weiter. (wir haben die Funktion rekursiv aufgerufen) Danach steht die Anweisung die Daten des Elements auszugeben."

also läuft die Funktion x mal, und wenn die x-te Funktion beendet wird, weil next == NULL ist, wird dann die nochlaufende vorletzte Funktion beendet, und da hier jetzt aber next nicht mehr verändert wird, und also immer noch NULL ist, wird das if übersprungen und die Daten werden mit dem next dieser vorletzten Funktion ausgegeben, aber das next wird wieder nicht verändert ... und so weiter ...
Ich glaub, jetzt hab' ich's verstanden. DANKE
 
Zurück