ein Kapitel zurück                                           ein Kapitel weiter

Nun wollen wir unser Programm vom Kapitel zuvor mit einigen Funktionen erweitern. Zuerst schreiben wir eine Funktion zum löschen einer Ganzen Liste auf einmal. Die Funktion bietet eigentlich nicht viel neues...

void loesche_alles()
{
 struct angestellt *zeiger, *zeiger1;

/*Ist überhaupt eine Liste zum löschen vorhanden*/
 if(anfang != NULL)
  {
/*Es ist eine vorhanden....*/
   zeiger=anfang->next;
   while(zeiger != NULL)
    {
     zeiger1=anfang->next->next;
     anfang->next=zeiger1;
     free(zeiger->next);
     free(zeiger);
     zeiger=zeiger1;
    }
/*Jetzt löschen wir erst den Anfang der Liste*/
  free(anfang->next);
  free(anfang);
  anfang=NULL;
  printf("Liste erfolgreich gelöscht!!\n");
 }
 else
    fprintf(stderr,"Keine Liste zum löschen vorhanden!!\n");
}

Zuallererst überprüfen wir wieder ob überhaupt ein Liste zum Löschen vorhanden ist. Anschließend bekommt unser Zeiger zeiger die Adresse vom 2.Element (anfang->next)...


Lineare Listen


Nun übergeben wir mittels....

zeiger1=anfang->next->next;

...die Adresse des übernächsten von dem Zeiger anfang (In unserem Fall das 3.Element). Sie sehen es ist auch möglich mit next, da ja struct angestellt *next in jeder einzelnen Struktur vorhanden ist, mehrere Adressen zu überspringen. Natürlich könnten sie auch verwenden zeiger=anfang->next->next->next, aber dann wird zu 100% ihr Programm abstürzen oder zumindest ein undefiniertes Verhalten ans Licht bringen, da unser Zeiger zeiger irgendwann auf eine nicht bekannte Adresse zeigen würde die gar nicht vorhanden ist. Bildlich hätten wir somit folgendes...


Lineare Listen


Nun übergeben wir mit....

anfang->next=zeiger1;

...unserem 1.Element als next - Zeiger die Adresse auf die zeiger1 zeigt...


Lineare Listen


Man könnte somit wieder sagen das wir das Element auf das der Zeiger zeiger zeigt ausgehängt haben. Nun geben wir den Speicher mittels....

free(zeiger->next);
free(zeiger);

...frei. Zuerst "hängen" wir noch den next Zeiger vom Element auf das zeiger1 zeigt aus (müsste jetzt noch nicht sein aber wir wollen es uns gleich so angewöhnen). Anschließend geben wir mit free(zeiger) den Speicher auf den zeiger zeigt frei. Jetzt bekommt nur noch unser Zeiger zeiger die Adresse von zeiger1. Somit sieht es jetzt folgendermaßen aus...


Lineare Listen


Nun geht es wieder von neuem mit der while - Schleife los wie bildlich ohne Kommentare folgt ...


Lineare Listen






Lineare Listen






Lineare Listen


Somit hätten wir die Abbruchbedienung für unsere while - Schleife. Unser Zeiger zeiger zeigt jetzt auf NULL. Jetzt brauchen wir nur noch den Anfang löschen...

free(anfang->next);
free(anfang);
anfang=NULL;

Zur Sicherheit übergeben wir unserem Zeiger auf das 1.Element noch den NULL - Zeiger, da selbst wenn wir den Speicher freigeben, zeigt unser Zeiger anfang immer noch auf die Ursprüngliche Stelle. Dabei kann es leicht zu Programmierfehler kommen.

Jetzt wollen wir eine Funktion schreiben bei der ein neues Element nach Alphabet eingefügt wird. Denn wozu die Liste erst danach sortieren wenn man mit einer kleinen Funktion den Namen nach Alphabet eingeben kann. Wir beschränken uns vorerst auf dem Nachnamen. Nun gibt es 4 Möglichkeiten die uns begegnen können beim Alphabetischen Einfügen der Namen. Es ist noch gar keine Element in der Liste vorhanden und das von uns eingegebene ist das erste Element (anfang==NULL).

Das von uns Eingegeben Element ist das größte und wir somit hinten angehängt. (zeiger==NULL) Das von uns Eingegebene Element ist das kleinste und wird ganz an den Anfang eingefügt.

(zeiger==anfang)

Die letzte Möglichkeit ist gleichzeitig die schwierigste. Das Element muss irgendwo in der Mitte eingefügt werden. Diese 4 Möglichkeiten müssen wir nun in einer Funktion durchprüfen und dementsprechende Maßnamen ausführen. Zuerst wieder unser Funktionskopf...

void sortiert_eingeben(char n[],char v[],int at,int am,int aj,
                                  int et,int em,int ej,long geh)
{
  struct angestellt *zeiger, *zeiger1;

Nun wollen wir unseren 1.Fall überprüfen, nämlich ob überhaupt ein Element in der Liste vorhanden ist...

if(anfang==NULL)
   anhaengen(n,v,at,am,aj,et,em,ej,geh);

Falls noch kein Element in der Liste vorhanden ist wird unsere Funktion anhaengen() ausgeführt. Nachdem es schon mindestens ein Element in der Liste gibt wollen wir nun unser neues Element vergleichen.....

zeiger=anfang;
while(zeiger != NULL && (strcmp(zeiger->name,n)<0))
   zeiger=zeiger->next;

Wir durchlaufen nun die ganze Kette so lange bis wir ans Ende gekommen sind (zeiger == NULL) oder bis unser neuer Name größer oder gleich mit dem Namen ist auf dem zeiger->name zeigt. Die erst Möglichkeit die wir nun überprüfen ist ob unser Zeiger zeiger auf NULL zeigt und somit auf das Ende der Kette...

if(zeiger==NULL)
   anhaengen(n,v,at,am,aj,et,em,ej,geh); 

Falls ja brauchen wir wieder nur die Funktion anhaengen, aufrufen und unser neues Element, das ja nun das "größte" ist ans Ende der Liste hängen. Die nächste Möglichkeit die wir haben ist das unser Element das kleinste ist und ganz an den Anfang gehört....

else if(zeiger==anfang)
{
 anfang=(struct angestellt *)malloc(sizeof(struct angestellt));
 strcpy(anfang->name,n);
 strcpy(anfang->vorname,v);
 anfang->alter.tag=at;
 anfang->alter.monat=am;
 anfang->alter.jahr=aj;
 anfang->eingest.tag=et;
 anfang->eingest.monat=em;
 anfang->eingest.jahr=ej;
 anfang->gehalt=geh;
 anfang->next=zeiger;
}

Dies nun bildlich folgendermaßen aus :

anfang == zeiger



Lineare Listen




anfang=(struct angestellt *)malloc(sizeof(struct angestellt)); 



Lineare Listen




anfang->next=zeiger; 



Lineare Listen


Nun haben wir noch ein letzte Möglichkeit. Wir müssen das Element irgendwo dazwischen reinschieben....

else
{
 zeiger1=anfang;
/*Wir suchen das Element das vor dem Zeiger zeiger steht*/
 while(zeiger1->next != zeiger)
    zeiger1=zeiger1->next;
 zeiger=(struct angestellt *)malloc(sizeof(struct angestellt));
 strcpy(zeiger->name,n);
 strcpy(zeiger->vorname,v);
 zeiger->alter.tag=at;
 zeiger->alter.monat=am;
 zeiger->alter.jahr=aj;
 zeiger->eingest.tag=et;
 zeiger->eingest.monat=em;
 zeiger->eingest.jahr=ej;
 zeiger->gehalt=geh;
/*Wir fügen das neue Element ein*/
 zeiger->next=zeiger1->next;
 zeiger1->next=zeiger;
} 

Nehmen wir mal an wir müssten zwischen dem 2. und 3. Element eine neues einfügen...




Unser Zeiger zeiger zeigt somit auf das 3. Element. Jetzt benötigen wir mittels...

while(zeiger1->next != zeiger)
    zeiger1=zeiger1->next;

...die Adresse ein Element vor dem auf das unser Zeiger zeiger zeigt und übergeben diese Adresse an zeiger1...


Lineare Listen


Nun benötigen wir mittels....

zeiger=(struct angestellt *)malloc(sizeof(struct angestellt));

...neuen Speicherplatz für unser neues Element...


Lineare Listen


Nach der Eingabe unseres neuen Elementes bekommt der next - Zeiger des neuen Elementes die Adresse auf die auch unser next - Zeiger von zeiger1 zeigt...

zeiger->next=zeiger1->next;

Somit ergibt sich folgendes Bild.....


Lineare Listen


Jetzt müssen wir nur noch den next - Zeiger von zeiger1 auf die Adresse zeigen lassen auf die unser Zeiger zeiger zeigt (zeiger1->next=zeiger;)....


Lineare Listen


Somit hätten wir die Funktion sortiert_eingeben fertig. Hier noch mal die komplette Funktion...

void sortiert_eingeben(char n[],char v[],int at,int am,int aj,
                                int et,int em,int ej,long geh)
{
 struct angestellt *zeiger, *zeiger1;

/*Ist es das 1.Element der Liste ? */
 if(anfang==NULL)
    anhaengen(n,v,at,am,aj,et,em,ej,geh);
/*Es ist nicht das 1.Element. Wir suchen nun so lange bis das
gesuchte Element gefunden wird oder wir auf NULL stossen*/
 else
  {
   zeiger=anfang;
   while(zeiger != NULL && (strcmp(zeiger->name,n)<0))
   zeiger=zeiger->next;
/*Falls der Zeiger auf NULL zeigt können wir unser Element hinten
anhängen da unser neues Element das "grösste" zu sein scheint */
   if(zeiger==NULL)
       anhaengen(n,v,at,am,aj,et,em,ej,geh);
/*Ist unser neues Element das kleinste und somit kleiner als das
1.Element so müssen wir es an den Anfang hängen */
   else if(zeiger==anfang)
    {
     anfang=(struct angestellt *)malloc(sizeof(struct angestellt));
     strcpy(anfang->name,n);
     strcpy(anfang->vorname,v);
     anfang->alter.tag=at;
     anfang->alter.monat=am;
     anfang->alter.jahr=aj;
     anfang->eingest.tag=et;
     anfang->eingest.monat=em;
     anfang->eingest.jahr=ej;
     anfang->gehalt=geh;
     anfang->next=zeiger;
    }
/*Die letzt Möglichkeit ist das wir das Element irgendwo in der Mitte
einfügen müssen*/
   else
    {
     zeiger1=anfang;
/*Wir suchen das Element das vor dem Zeiger zeiger steht*/
     while(zeiger1->next != zeiger)
          zeiger1=zeiger1->next;
     zeiger=(struct angestellt *)malloc(sizeof(struct angestellt));
     strcpy(zeiger->name,n);
     strcpy(zeiger->vorname,v);
     zeiger->alter.tag=at;
     zeiger->alter.monat=am;
     zeiger->alter.jahr=aj;
     zeiger->eingest.tag=et;
     zeiger->eingest.monat=em;
     zeiger->eingest.jahr=ej;
     zeiger->gehalt=geh;
/*Wir fügen das neue Element ein*/
     zeiger->next=zeiger1->next;
     zeiger1->next=zeiger;
    }/*Ende else*/
  }/*Ende else*/
}

Unser Programm werden wir in den nächsten Kapiteln weiterverwenden und verbessern. Hier und da könnten wir unser Programm jetzt zwar noch ein wenig verbessern, aber das ist jetzt nicht so wichtig. Wichtig ist mir nur das sie die Grundlage von verketteter Listen verstanden haben. Denn Quellcode des Programms können sie hier downloaden : Programm kette3.c herunterladen (kette3.c)

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf