Institut für Informatik C-­‐Kurs 09 Dynamische Datenstrukturen Dipl.-­‐Inf. Jörn Hoffmann jhoff[email protected]­‐leipzig.de Universität Leipzig InsAtut für InformaAk Technische InformaAk Flexible Datenstrukturen Institut für Informatik Dynamische Datenstrukturen • Strukturen, die zur Laufzeit angelegt werden • Skalierbar, Flexibel • Benötigen zusätzliche Verwaltungs- und Zugriffsoperationen Inhalt 1. Elementzugriff 2. Funktionszeiger 3. Lineare Listen 4. Bäume Jörn Hoffmann *(ptr).element ó ptr->element int (*ptr)(int); knoten->next; knoten->a | knoten->b; C-Kurs Folie 2 Zeiger Elementzugriff Institut für Informatik Syntax • *(Strukturzeiger).Komponenten; • Strukturzeiger -> Komponenten ; Semantik • Zugriff auf die Komponente einer struct bzw. union, auf die der Strukturzeiger verweist • Vereinfachung der Schreibweise der beiden Operationen 1. Zeiger Dereferenzierung 2. Komponentenzugriff Jörn Hoffmann C-Kurs Folie 3 Zeiger Elementzugriff Institut für Informatik Beispiel // zugriff.c! typedef struct ! {! !char name[100];! !int alter;! } person_t;! ! person_t pers = {“Max“, 25};! person_t *ptr = &pers;! ! printf (“pers.name = %s, pers.alter = %d\n“, pers.name, pers.alter);! printf (“ptr->name = %s, ptr->alter = %d\n“, ptr->name, ptr->alter);! Jörn Hoffmann C-Kurs Folie 4 Funktionszeiger Institut für Informatik Syntax • Deklaration : Rückgabetyp (*Funktionszeigervariable)( Parameterliste ) • Zuweisung : Funktionszeigervariable = Funktionsname; • Aufruf : Funktionszeigervariable (Parameter); Semantik • Deklarieren einer Zeigervariablen, die auf eine Funktion mit dem angegebene Rückgabetypen und Parameterliste verweisen kann. • Zuweisen des Funktionszeigers einfach über Angabe des Funktionsnamens • Aufruf analog wie bei Funktion direkt Nutzen • Wiederverwendung einer Implementierung • Generische Programmierung Jörn Hoffmann C-Kurs Folie 5 Institut für Informatik Beispiel! // funktionszeiger.c! #include <stdio.h>! ! void printZahl(int zahl)! {! printf("%d\n", zahl);! }! ! int main() ! {! int (*ptr1) (const char*, ...) = printf;! void (*ptr2)(int) = printZahl;! ! ptr1("Hallo Welt\n"); (*ptr2)(2); ! return 0;! // Aufruf ! // Aufruf (alternativ)! }! Jörn Hoffmann C-Kurs Folie 6 Flexible Datenstrukturen Zweck Institut für Informatik Anforderung • Programm zur Verwaltung von Kunden benötigt • Viele Kunden • Hohes Neuaufkommen von Kunden • Suche und Sortierung nötig Jörn Hoffmann C-Kurs Folie 7 Statisches Array Institut für Informatik 1. Lösung (Statisches Array)! typedef struct! {! !int knr;! !char *name;! !/* ... */! }kunde_t;! ! // Statisches Array! kunde_t kundendaten[10000];! Eigenschaften • Einfach • Speicherverschwendung • Keine flexible Verwaltung • Aufwändige Sortierung und Suche Jörn Hoffmann C-Kurs Folie 8 Dynamisches Array Institut für Informatik 2. Lösung (Dynamisches Array)! typedef struct! {! !int knr;! !char *name;! !/* ... */! }kunde_t;! ! // Dynamisches Array (Halbstatisch)! kunde_t *kundendaten = malloc(anzahlKunden * sizeof(kunde_t));! Eigenschaften • Bedarfsgerechte Speichernutzung • Aufwändiges Umkopieren bei neuen Kunden • Aufwändige Sortierung und Suche Jörn Hoffmann C-Kurs Folie 9 Lineare Liste Institut für Informatik 3. Lösung (Lineare Liste)! typedef struct _knoten! {! kunde_t element;! struct _knoten *next;! } knoten_t;! ! // Lineare Liste! knoten_t *k1 = malloc(sizeof(knoten_t));! knoten_t *k2 = malloc(sizeof(knoten_t));! k1.next = k2;! k2.next = NULL;! Eigenschaften • Flexibel, Skalierbar • Geringer Mehraufwand durch indirekte Zeigerzugriffe Jörn Hoffmann C-Kurs Folie 10 Lineare Liste Institut für Informatik Lineare Liste • Dynamische Datenstruktur • Verwaltung von Elementen eines Typs • Verknüpft durch Zeiger • Kopf-Zeiger bestimmt aktuelle Einfügeposition • Letztes Element verweist auf NULL *kopf *(kopf.next) NULL kopf Jörn Hoffmann element next element C-Kurs next Folie 11 Lineare Liste Einfügen (Idee) Institut für Informatik Einfügen • Ermittlung des Einfügeplatzes • Änderung von zwei Verweisen (1) Vorgänger auf neues Element verweisen (2) Nachfolger im neuen Element setzen Neuer Knoten element next (1) (2) *kopf Listenende NULL kopf Jörn Hoffmann element next element C-Kurs next Folie 12 Lineare Liste Einfügen Institut für Informatik 0. Funktion Aufrufen • Funktion aufrufen • Parameter kopf zeigt auf Anfang der Liste • Parameter neuerKnoten wird fertig initialisiert übergeben • Element-Wert wird für Vergleiche benötig neu element next *kopf *next *next NULL ... kopf element Jörn Hoffmann next element next C-Kurs element next Folie 13 Lineare Liste Einfügen Institut für Informatik 1. Einfügeplatz finden • Liste mittels Schleife durchsuchen • Entscheidung ob aktueller Knoten durch Neuen ersetzen werden soll • Falls ja, Suche beenden • Falls nein, • Speicheradresse des Next-Zeigers in Hilfszeiger ablegen • Nächsten Knoten wählen neu hilf element *kopf next *next *next NULL ... kopf element Jörn Hoffmann next element next C-Kurs element next Folie 14 Lineare Liste Einfügen Institut für Informatik 2. Knoten einfügen • Wert des next-Zeigers vom neuen Knoten auf aktuellen Knoten setzen neu hilf element *kopf next *next, neu->next *next NULL ... kopf element Jörn Hoffmann next element next C-Kurs element next Folie 15 Lineare Liste Einfügen Institut für Informatik 3. Vorgänger anpassen • Next-Zeiger vom Vorgängerknoten auf neuen Knoten setzen • Dieser kann mittels Hilfszeiger direkt manipulieren werden neu hilf element *kopf next *next, neu->next *next NULL ... kopf element Jörn Hoffmann next element next C-Kurs element next Folie 16 Lineare Liste Einfügen Institut für Informatik 4. Liste anpassen • Kopf muss angepasst werden, falls es keinen Vorgänger gab • Kann ebenfalls über Hilfszeiger direkt manipuliert werden • Hilfszeiger muss am Anfang auf Kopf verweisen neu hilf element next neu->next *next NULL ... kopf Jörn Hoffmann element next C-Kurs element next Folie 17 Lineare Liste Einfügen Institut für Informatik 4. Fertig • Knoten ist jetzt eingefügt • Kopf wurde möglicherweise verändert *kopf *next *next NULL ... kopf element Jörn Hoffmann next element next C-Kurs element next Folie 18 Lineare Liste Beispiel Institut für Informatik void knotenEinfuegen(knoten_t **kopf, knoten_t *neuerKnoten)! {! knoten_t **hilf, *knoten;! ! // Aktuellen Knoten auf Listenanfang setzen! knoten = *kopf;! hilf = kopf;! ! // Finden der Einfügeposition! while (knoten != NULL) ! {! if(knoten->element > neuerKnoten->element)!// Vergleich zur Entscheidung! break; ! ! hilf = &knoten->next; // Adresse des Next-Zeiger speichern (kann direkt manipuliert werden)! knoten = knoten->next; // Nächster Knoten! }! ! // Vorhandene Knoten an neuen Knoten anfügen! neuerKnoten->next = knoten; ! ! // Vorgänger bzw. Kopf direkt anpassen! *hilf = neuerKnoten;! }! Jörn Hoffmann C-Kurs Folie 19 Dr. Monika Meiler 13.3 Spezielle verkettete lineare Listen und Bäume 13.3.1 Listen Institut für Informatik Lineare Listen Typen Einfach verkettete lineare Listen ... anfang NULL Keller ( Stack, lifo-Prinzip, last in first out): Elemente können nur am Anfang angehängt und entfernt werden. Warteschlange ( Queue, fifo-Prinzip, first in first out): Elemente werden stets am Ende angehängt und am Anfang entfernt. Zyklisch verkettete lineare Listen (Listenende zeigt auf den Anfang): anfang ... Doppelt verkettete lineare Listen (Verweis auf Vorgänger und Nachfolger): Jörn Hoffmann ... C-Kurs Folie 20 ... ... Keller ( Stack, lifo-Prinzip, last in first out): Elemente können nur am Anfang angehängt und entfernt werden. Warteschlange ( Queue, fifo-Prinzip, first in first out): Elemente werden stets am Ende angehängt und am Anfang entfernt. Lineare Listen Typen Institut für Informatik Zyklisch verkettete lineare Listen (Listenende zeigt auf den Anfang): anfang ... Doppelt verkettete lineare Listen (Verweis auf Vorgänger und Nachfolger): ... ... ... Mehrfach verkettete lineare Listen (Verweis auf die nächste Gruppe von Elementen): ... ... ... Allgemeine Listen erhält man, wenn man als Datentyp der Elemente wiederum Listen zulässt. C-Kurs Folie 21 Auch hier gibt es gewisse Strategien zum Suchen, Einfügen und Entfernen von Elementen, insbesondere um große Datenmengen schnell zu verarbeiten, die aber programmiertechnisch Bäume wesentlich aufwendiger sind. Institut für Informatik Wurzel NULL NULL NULL NULL Blatt NULL Jörn Hoffmann NULL NULL C-Kurs NULL Folie 22 Bäume Institut für Informatik Bäume • Wurzel • Ist Ausgezeichnetes Element (Zugriffspunkt) • Hat keine Vorgänger • Element • Hat genau ein Vorgänger • Hat beliebig viele Nachfolger • Blatt • ist Element ohne Nachfolger • Blätter können unterschiedliche Tiefe besitzen Jörn Hoffmann C-Kurs Folie 23 Bäume Binärbäume Universität Leipzig Institut für Informatik Institut für Informatik Dr. Monika Meiler 13.3.2 Bäume Bäume: Ein Baum hat ein ausgezeichnetes Element, die Wurzel. Diese hat keinen Vorgänger. Jedes weitere Element eines Baumes besitzt genau einen Vorgänger und beliebig viele Nachfolger. Elemente ohne Nachfolger nennt man Blätter. Binärbaum • Alle Elemente besitzen höchstens zwei Nachfolger Binärbäume: • Viele Strategien zum Suchen, Einfügen, Entfernen von höchstens Elementen bekannt Ein Binärbaum ist ein Baum, dessen Elemente zwei Nachfolger besitzen. • Insb. um große Datenmengen zu verarbeiten Auchschnell hier gibt es gewisse Strategien zum Suchen, Einfügen und Entfernen von Elementen, insbesondere um große Datenmengen schnell zu verarbeiten, die aber programmiertechnisch wesentlich aufwendiger sind. • Programmiertechnisch aufwendig Wurzel NULL NULL NULL NULL Blatt NULL Jörn Hoffmann C-Kurs NULL NULL NULL Folie 24