C-Programmierung: Verkette Listen
Aus Wikibooks
Beim Programmieren in C kommt man immer wieder zu Punkten, an denen man feststellt, dass man mit einem Array nicht auskommt. Diese treten zum Beispiel dann ein, wenn man eine unbekannte Anzahl von Elementen verwalten muss. Mit den Mitteln, die wir jetzt kennen, könnte man beispielsweise für eine Anzahl an Elementen Speicher dynamisch anfordern und wenn dieser aufgebraucht ist, einen neuen größeren Speicher anfordern, den alten Inhalt in den neuen Speicher schreiben und dann den alten wieder löschen. Klingt beim ersten Hinsehen ziemlich ineffizient, Speicher allokieren, füllen, neu allokieren, kopieren und freigeben. Also lassen Sie uns überlegen, wie wir das Verfahren optimieren können.
[Bearbeiten] 1. Überlegung:
Wir fordern vom System immer nur Platz für ein Element an. Vorteil: Jedes Element hat einen eigenen Speicher und wir können jetzt für neue Elemente einfach einen malloc ausführen. Weiterhin sparen wir uns das Kopieren, da jedes Element von unserem Programm eigenständig behandelt wird. Nachteil: Wir haben viele Zeiger, die jeweils auf ein Element zeigen und wir können immer noch nicht beliebig viele Elemente verwalten.
[Bearbeiten] 2. Überlegung:
Jedes Element ist ein komplexer Datentyp, welcher einen Zeiger enthält, der auf ein Element gleichen Typs zeigen kann. Vorteil: wir können jedes Element einzeln allokieren und so die Vorteile der ersten Überlegung nutzen, weiterhin können wir nun in jedem Element den Zeiger auf das nächste Element zeigen lassen, und brauchen in unserem Programm nur einen Zeiger auf das erste Element. Somit ist es möglich, beliebig viele Elemente zur Laufzeit zu verwalten. Nachteil: Wir können nicht einfach ein Element aus der Kette löschen, da sonst kein Zeiger mehr auf die nachfolgenden existiert.
[Bearbeiten] Die einfach verkettete Liste
Die Liste ist das Resultat der beiden Überlegungen, die wir angestellt haben. Die einfachste Art, eine verkettete Liste zu erzeugen, sieht man im folgenden Beispielquelltext (welcher nicht funktioniert):
-
#include <stdio.h> -
#include <stdlib.h> -
-
struct element {
-
int value; // der Wert des Elements -
struct element *next; // das nächste Element -
};
-
-
void append(struct element ***lst, struct element *new)
-
{ -
struct element *lst_iter = *lst;
-
-
if ( lst_iter!= NULL ) { // sind Elemente vorhanden
-
while (lst_iter->next != NULL ) // suche das letzte Element -
lst_iter=lst_iter->next; -
lst_iter->next=new; // Hänge das Element hinten an -
} -
else // wenn die liste leer ist, bin ich das erste Element
-
*lst=new; -
} -
-
int main(int argc, char *argv[])
-
{ -
struct element *first; -
struct element *einE; -
-
if (argc > 1) { -
printf("Zu viele Parameter fuer %s \n", argv[0]); -
return EXIT_FAILURE; -
} -
first = NULL; // init. die Liste mit NULL = leere liste -
einE = malloc(sizeof(*einE)); // erzeuge ein neues Element -
einE->value = 1; -
einE->next = NULL; // Wichtig für das Erkennen des Listenendes -
-
append(&first, einE); // füge das Element in die Liste ein -
-
return EXIT_SUCCESS; -
}