Einfhrung rekursiver Datenstrukturen in C Timm Grams Fachhochschule

![Benutzerdefinierte Datentypen Der Strukturtyp (Beispiel: komplexe Zahlen) struct complex {float x, y; } a[3] Benutzerdefinierte Datentypen Der Strukturtyp (Beispiel: komplexe Zahlen) struct complex {float x, y; } a[3]](https://slidetodoc.com/presentation_image_h/f5c99c9b11bd842c547029f5f26aac9b/image-2.jpg)
![Benutzerdefinierte Datentypen Deklarationsspezifikator (declaration-specifier) struct complex {float x, y; } a[3] = {{3, 4}, Benutzerdefinierte Datentypen Deklarationsspezifikator (declaration-specifier) struct complex {float x, y; } a[3] = {{3, 4},](https://slidetodoc.com/presentation_image_h/f5c99c9b11bd842c547029f5f26aac9b/image-3.jpg)
![Benutzerdefinierte Datentypen Deklarator (declarator) struct complex {float x, y; } a[3] = {{3, 4}, Benutzerdefinierte Datentypen Deklarator (declarator) struct complex {float x, y; } a[3] = {{3, 4},](https://slidetodoc.com/presentation_image_h/f5c99c9b11bd842c547029f5f26aac9b/image-4.jpg)
![Benutzerdefinierte Datentypen Initialisator (initializer) struct complex {float x, y; } a[3] = {{3, 4}, Benutzerdefinierte Datentypen Initialisator (initializer) struct complex {float x, y; } a[3] = {{3, 4},](https://slidetodoc.com/presentation_image_h/f5c99c9b11bd842c547029f5f26aac9b/image-5.jpg)


![Besser: Array von Pointern und dynamische Speicherreservierung struct complex *Bahn[1000]; Bahn[2]= malloc(sizeof(struct complex)); Bahn[2]->x=0. Besser: Array von Pointern und dynamische Speicherreservierung struct complex *Bahn[1000]; Bahn[2]= malloc(sizeof(struct complex)); Bahn[2]->x=0.](https://slidetodoc.com/presentation_image_h/f5c99c9b11bd842c547029f5f26aac9b/image-8.jpg)

![Garbage (memory leak) Bahn[2]= malloc(sizeof(struct complex)); Stack 0 1 2 0 0 0 999 Garbage (memory leak) Bahn[2]= malloc(sizeof(struct complex)); Stack 0 1 2 0 0 0 999](https://slidetodoc.com/presentation_image_h/f5c99c9b11bd842c547029f5f26aac9b/image-10.jpg)
![Garbage (memory leak) Bahn[2]= malloc(sizeof(struct complex)); Stack 0 1 2 0 0 0 999 Garbage (memory leak) Bahn[2]= malloc(sizeof(struct complex)); Stack 0 1 2 0 0 0 999](https://slidetodoc.com/presentation_image_h/f5c99c9b11bd842c547029f5f26aac9b/image-11.jpg)
![Baumelnder Zeiger (dangling reference) free(Bahn[2]); Stack 0 1 2 0 0 0 999 0 Baumelnder Zeiger (dangling reference) free(Bahn[2]); Stack 0 1 2 0 0 0 999 0](https://slidetodoc.com/presentation_image_h/f5c99c9b11bd842c547029f5f26aac9b/image-12.jpg)











- Slides: 23
Einführung rekursiver Datenstrukturen in C Timm Grams Fachhochschule Fulda Fachbereich Elektrotechnik und Informationstechnik © Timm Grams, Fulda, 15. 02
Benutzerdefinierte Datentypen Der Strukturtyp (Beispiel: komplexe Zahlen) struct complex {float x, y; } a[3] = {{3, 4}, {-6, 8}, { 9, -12}};
Benutzerdefinierte Datentypen Deklarationsspezifikator (declaration-specifier) struct complex {float x, y; } a[3] = {{3, 4}, {-6, 8}, { 9, -12}};
Benutzerdefinierte Datentypen Deklarator (declarator) struct complex {float x, y; } a[3] = {{3, 4}, {-6, 8}, { 9, -12}};
Benutzerdefinierte Datentypen Initialisator (initializer) struct complex {float x, y; } a[3] = {{3, 4}, {-6, 8}, { 9, -12}};
Beispiel: ebene Bahnkurve Die Bahn eines Roboters in der Ebene ist mittels einer Punktfolge zu beschreiben: (0. 25, 0. 20), (0. 12, 0. 75), . . . , (-1. 77, 4. 65). Für die Punktfolge wird ein Array komplexer Zahlen eingeführt: struct complex Bahn[1000];
Nachteil des komplexen Arrays Die maximale Anzahl von Elementen der Bahnkurve (hier: 1000) muss dem ungünstigsten Fall Rechnung tragen. Werden - wie hier - nur 100 Plätze tatsächlich benötigt, wird Speicherplatz vergeudet. Stack 0 x: 0. 25 y: 0. 20 1 x: 0. 12 y: 0. 75. . . 99 x: -1. 77 y: 4. 65 100 x: ? y: ? . . . 999 x: ? y: ?
Besser: Array von Pointern und dynamische Speicherreservierung struct complex *Bahn[1000]; Bahn[2]= malloc(sizeof(struct complex)); Bahn[2]->x=0. 25; Bahn[2]->y=0. 2; 0 1 2 0 0 0 x: 0. 25 y: 0. 2 Stack 999 0 Heap
Dynamische Variablen sind heikel Typische Programmierfehler und Probleme Erzeugung von Datenmüll und Verlust von Speicherplatz (garbage, memory leak) Baumelnde Zeiger (dangling references)
Garbage (memory leak) Bahn[2]= malloc(sizeof(struct complex)); Stack 0 1 2 0 0 0 999 0 Heap x: 0. 25 y: 0. 2
Garbage (memory leak) Bahn[2]= malloc(sizeof(struct complex)); Stack 0 1 2 0 0 0 999 0 Heap x: 0. 25 y: 0. 2
Baumelnder Zeiger (dangling reference) free(Bahn[2]); Stack 0 1 2 0 0 0 999 0 Heap x: 0. 25 Daten y: 0. 2 aus einem anderen Kontext
Nachteil des Pointer-Arrays Das Pointer-Array reduziert den Speicherbedarf etwas. Merklich wird der Effekt erst bei komplexeren Strukturen. Aber immer noch ist die maximale Anzahl der Listenelemente vorab zu schätzen. Bei Großzügigkeit wird Speicherplatz vergeudet. Bei Knausrigkeit ist eine spätere Programmänderung höchstwahrscheinlich. Ziel: Nur den Speicherplatz reservieren, der tatsächlich benötigt wird. Methode: Rekursive Datenstrukturen.
Rekursive Datenstrukturen in C Neudefinition: complex als rekursiver Datentyp struct complex {float x, y; struct complex *next; }; So wird man das Schlüsselwort struct los: #define complex struct complex {float x, y; complex *next; }; So ist es besser (weil vom Compiler kontrolliert): typedef struct complex {float x, y; struct complex *next; } complex;
Lineare Liste komplexer Zahlen Aufbau der Liste complex *p=0, *h; unsigned char c='j'; while(c=='j') { h=(complex*)malloc(sizeof(complex)); printf("n? x y = "); scanf("%f %f", &h->x, &h->y); h->next=p; p=h; printf("n? Weiter mit "j": "); scanf("%1 s", &c); }
Aufbau der linearen Liste Stack p 0 h ? Heap x: 0. 25 y: 0. 2 next: 0 h= (complex*)malloc. . . ; printf("n? x y = "). . . ; h->next=p; p=h;
Aufbau der linearen Liste Stack p 0 h= (complex*)malloc. . . ; Heap x: 0. 25 y: 0. 2 next: 0
Aufbau der linearen Liste Stack p 0 h 0 Heap x: 0. 25 y: 0. 2 next: 0 x: 1. 2 y: 0. 75 next: h= (complex*)malloc. . . ; printf("n? x y = "). . . ; h->next=p; p=h;
Aufbau der linearen Liste Stack p 0 h 0 Heap x: 0. 25 y: 0. 2 next: 0 x: 1. 2 y: 0. 75 next: h= (complex*)malloc. . . ; printf("n? x y = "). . . ; h->next=p; p=h;
Aufbau der linearen Liste „Begradigung der Zeichnung“ Stack p 0 h 0 Heap x: 1. 2 y: 0. 75 next: x: 0. 25 y: 0. 2 next: 0 Im Speicher (Heap) werden die Objekte NICHT bewegt!
Lineare Liste Der zuletzt eingegebene Punkt ist erstes Element der Liste. Durchlaufen der Elemente in Eingabereihenfolge mittels rekursiver Funktion. Anmerkung: Man hätte die Liste gleich in richtiger Folge aufbauen oder nachträglich umordnen können. Dann wäre ein Durchlaufen mittels Iteration möglich: cur=p; while (cur) {. . . cur=cur->next; }
Ausgabe mit rekursiver Funktion void show(complex *p) { if (p!=0) { show(p->next); printf("n%10 e", p->x, p->y); } }
Ende der Demonstration