Verkettete Liste
-
mh ok danke :).
Ich hab jetzt daraus eine doppelt verkettete Liste gemacht:
spielzug * file2zuege(char filename[]) { FILE* infile = NULL; spielzug* liste = NULL; spielzug* act_spielzug = NULL; spielzug* letzer_spielzug = NULL; spielzugfile buffer; if ( ( infile = fopen(filename,"rb")) != NULL) { while(fread(&buffer,sizeof(spielzugfile),1,infile) == 1) { act_spielzug = malloc(sizeof(spielzug)); if (act_spielzug == NULL) { exit(-1); } act_spielzug->posx=buffer.posx; act_spielzug->posy=buffer.posy; act_spielzug->zeichen=buffer.zeichen; act_spielzug->next=NULL; if (liste == NULL) { liste = act_spielzug; act_spielzug->prev=NULL; } else { letzer_spielzug->next= act_spielzug; act_spielzug->prev=letzer_spielzug; } letzer_spielzug=act_spielzug; } fclose(infile); } return liste; }
Ich werden jetzt die einzelnen While-Durchgänge kurz erläutern:
1. Durchgang:
Hier zeigt liste auf den 1. Spielzug.2. Durchgang:
act_spielzug zeigt auf das 2. Element. Die adresse des 2. Element wird nun zu letzer_spielzug->next kopiert.
liste->next ist gleich letzer_spielzug->next warum sind die beiden ident? Wo sieht man das?Ich verstehe das noch immer nicht, warum den letzer_Spielzug->next genau die gleiche Adresse hat wie liste->next im 2. Durchgang?
act_spielzug hat doch auch nicht die selbe Adresse wie die beiden?
Bitte erklärt es mir.
Danke!
-
In welcher Zeile bist du denn?
letzer_spielzug zeigt auf den Vorgänger.
Also zeigt es beim 2. Element auf das 1. Element, welches auch Anfang der Liste ist und somit auch liste darauf zeigt.
-
Aso, sorry in Zeile 29
-
Nochmal kurz:
liste zeigt auf 1. Element
act_spielzug zeigt auf 2. Element
letzer_spielzug zeigt auf 1. Element
Dann ist letzer_spielzug->next das gleiche wie liste->nextliste | | | | +---------+ +->|1.Element| +---------+ +---------+ | next | ----> |2.Element| +---------+ +---------+ | next | ----> NULL +---------+ letzer_spielzug act_spielzug
Beim 3. Element sieht es dann so aus
liste | | | | +---------+ +->|1.Element| +---------+ +---------+ | next | ----> |2.Element| +---------+ +---------+ +---------+ | next | ----> |3.Element| +---------+ +---------+ | next | ----> NULL +---------+ letzer_spielzug act_spielzug
-
Danke! Jetzt verstehe ich wie das ganze zusammenhängt!
Und so siehts bei doppelt verketteten liste aus?
liste | | | | +---------+ +-> |1.Element| +---------+ +---------+ | next | ----> |2.Element| +---------+ +---------+ +---------+ NULL<---| prev | | next | ----> |3.Element| +---------+ +---------+ +---------+ |1.Element| <---- | prev | | next | ----> NULL +---------+ +---------+ +---------+ |2.Element| <---- | prev | +---------+ +---------+ |3.Element| +---------+ letzer_spielzug act_spielzug
liste->prev muss immer NULL sein, genau wie liste->next->next->next.
D.h. also, dass man auf mehrere Arten auf z.B. das 1. Element zugreifen kann, richtig?
Mit dem liste-pointer direkt und mit liste->next->prev.
Und auf 2. Element: liste->next, oder liste->next->next->prev.Ist richtig so oder?
Und wie kann ich von hinten nach vorne ausgeben, also den prev-pointer zu hilfe nehmen beim Ausgeben? Ich hab mir das so gedacht, das ich das Ende finde, also der pointer muss NULL sein. Und dann halt immer mit ->prev zurück gehe und ausgebe. Aber iwie klappt das nicht so recht.
int main() { spielzug * alle_zuege = NULL; spielzug * zuege_first = NULL; spielzug * alle_zuege1 = NULL; zuege_first = file2zuege("zuege.dat"); alle_zuege=zuege_first; alle_zuege1=zuege_first; while(alle_zuege != NULL) { printf("x:%d,y:%d,stein:%c\n",alle_zuege->posx,alle_zuege->posy,alle_zuege->zeichen); alle_zuege=alle_zuege->next; } printf("------------------\n"); while(alle_zuege1 != NULL) { alle_zuege1=alle_zuege1->next; } while(alle_zuege1->prev != NULL) { printf("x:%d,y:%d,stein:%c\n",alle_zuege->posx,alle_zuege->posy,alle_zuege->zeichen); alle_zuege1=alle_zuege1->prev; } return 0; }
Was mache ich da genau falsch?
Könntet ihr mir vielleicht noch bitte Tipps geben wie ich die GANZE Liste löschen kann?
-
EDIT:
liste | | | | +---------+ +-> |1.Element| +---------+ +---------+ | next | ----> |2.Element| +---------+ +---------+ +---------+ NULL<---| prev | | next | ----> |3.Element| +---------+ +---------+ +---------+ |1.Element| <---- | prev | | next | ----> NULL +---------+ +---------+ +---------+ |2.Element| <---- | prev | +---------+ +---------+ |3.Element| +---------+ letzer_spielzug act_spielzug
-
Welchen Wert hat
alle_zuege1
in Zeile 23?
Tipp:printf("alle_zuege1: %p\n", alle_zuege1);
Die Liste musst du Knoten für Knoten löschen. So wie du sie auch angelegt hast.
-
alle_zuege1 zeigt in Zeile 23 auf NULL.
Also wir sind am Ende der Kette.
-
Das Programm geht doch aber weiter.
Was meinst du ergibt dannalle_zuege1->prev
in Zeile 24?
-
Mh ok das ist dann natürlich auch 0.
Aber wie könnte ich das anders machen?
-
Nein, das ist nicht NULL.
Der Zugriffsversuch auf NULL->next (alle_zuege1->next
) ist in diesem Fall verboten, da dir der Speicher dort nicht gehört.[quote="liste1]Aber wie könnte ich das anders machen?[/quote]
Wie wäre es, wenn du dir das letzte Element merkst?