Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

G.Heyer Algorithmen und Datenstrukturen 1 Kapitel 3: Listen Lineare Liste: endliche Folge von Elementen eines Grundtyps (n>=0), leere Liste <> falls n=0.

Ähnliche Präsentationen


Präsentation zum Thema: "G.Heyer Algorithmen und Datenstrukturen 1 Kapitel 3: Listen Lineare Liste: endliche Folge von Elementen eines Grundtyps (n>=0), leere Liste <> falls n=0."—  Präsentation transkript:

1 G.Heyer Algorithmen und Datenstrukturen 1 Kapitel 3: Listen Lineare Liste: endliche Folge von Elementen eines Grundtyps (n>=0), leere Liste <> falls n=0 Listenelemente besitzen Schlüssel, eigentliche Information und ggf. weitere Komponenten (z.B. Zeiger). Operationen: Einfügen, Entfernen, Suchen Implementierungen: 1. Sequentiell (Arrays), 2. Dynamisch (Zeiger) Vorteile sequentieller Speicherung: schnelle Suchverfahren falls Sortierung vorliegt, da jedes Element über Indexposition direkt ansprechbar (O(1)) Nachteile sequentieller Speicherung: hoher Änderungsaufwand durch Verschiebekosten (O(n)) schlechte Speicherplatzausnutzung inflexibel bei starkem dynamischem Wachstum

2 G.Heyer Algorithmen und Datenstrukturen 2 Implementierung (Zeiger): Zeiger (*ptr).next zeigt auf a n (erleichtert Hintereinanderhängen von Listen). Notation in C: ptr->next praktische Realisierung: Verwendung 2er Dummy-Elemente, die Kopf und Ende repräsentieren. head -> |__|_| -> | a 1 | | ->... -> | a n | | -> | | | <- tail Eine Struktur für einfach verkettete Listenelemente typedef struct ListElmt_ { void *data; struct ListElmt_ *next; } ListElmt;

3 G.Heyer Algorithmen und Datenstrukturen 3 Einfach verkettete Listen: Eine Struktur für verkettete Listen typedef struct List_ { int size; int (*match)(const void *key1, const void *key2); void (*destroy)(void *data); ListElmt *head; ListElmt *tail; } List;

4 G.Heyer Algorithmen und Datenstrukturen 4 Einfach verkettete Listen: Public Interfaces void list_init(List *list, void (*destroy)(void *data)); void list_destroy(List *list); int list_ins_next(List *list, ListElmt *element, const void *data); int list_rem_next(List *list, ListElmt *element, void **data); #define list_size(list) ((list)->size) #define list_head(list) ((list)->head) #define list_tail(list) ((list)->tail) #define list_is_head(list, element) ((element) == (list)->head ? 1 : 0) #define list_is_tail(element) ((element)->next == NULL ? 1 : 0) #define list_data(element) ((element)->data) #define list_next(element) ((element)->next)

5 G.Heyer Algorithmen und Datenstrukturen 5 Einfach verkettete Listen: Initialisieren einer Liste void list_init(List *list, void (*destroy)(void *data)) { list->size = 0; list->destroy = destroy; list->head = NULL; list->tail = NULL; return; }

6 G.Heyer Algorithmen und Datenstrukturen 6 Einfach verkettete Listen: list_ins_next int list_ins_next(List *list, ListElmt *element, const void *data) { ListElmt *new_element; if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL) return -1; new_element->data = (void *)data; if (element == NULL) { if (list_size(list) == 0) list->tail = new_element; new_element->next = list->head; list->head = new_element; } else { if (element->next == NULL) list->tail = new_element; new_element->next = element->next; element->next = new_element;} list->size++; return 0; }

7 G.Heyer Algorithmen und Datenstrukturen 7 Einfach verkettete Listen: Nur sequentielle Suche möglich (sowohl im geordneten als auch ungeordneten Fall) Einfügen und Löschen eines Elementes mit Schlüssel K erfordert vorherige Suche

8 G.Heyer Algorithmen und Datenstrukturen 8 Implementierung (doppelt verkettet): Zeiger (*ptr).next zeigt auf das nachfolgende und (*ptr).previous gleichzeitig auf das vorhergehende Listenelement. head -> |__|_| | a 1 | |... | a n | | <- tail struct node {int key; struct node *next; struct node *previous; };

9 G.Heyer Algorithmen und Datenstrukturen 9 Implementierung (doppelt verkettet): Bewertung höherer Speicherplatzbedarf als bei einfacher Verkettung Aktualisierungsoperationen etwas aufwendiger (Anpassung der Verkettung) Suchaufwand in etwa gleich hoch, jedoch ggf. geringerer Suchaufwand zur Bestimmung des Vorgängers (PREVIOUS(p,L)) geringerer Aufwand für Operation DELETE(p,L) Flexibilität der Doppelverkettung besonders vorteilhaft, wenn Element gleichzeitig Mitglied mehrerer Listen sein kann (Multilist-Strukturen)

10 G.Heyer Algorithmen und Datenstrukturen 10 Implementierung (doppelt verkettet): Suchaufwand bei ungeordneter Liste erfolgreiche Suche c avg =(n+1)/2 (Standardannahme: zufällige Schlüsselauswahl, stochastische Unabhängigkeit der g. Schlüsselmenge) Einfügen oder Löschen eines Elementes konstante Kosten für Einfügen am Listenanfang Löschen verlangt meist vorherige Suche konstante Löschkosten bei positionsbezogenem Löschen und Doppelverkettung Sortierung bringt kaum Vorteile erfolglose Suche c avg =(n+1)/2 lineare Kosten für Einfügen in Sortierreihenfolge

11 G.Heyer Algorithmen und Datenstrukturen 11 Häufigkeitsgeordnete lineare Listen Zugriffshäufigkeiten für die einzelnen Elemente bekannt mittlere Suchkosten c avg (n)=1*p 1 +2*p 2 +3*p n*p n minimierte Suchkosten wenn p 1 >p 2 >...>p n Selbstorganisierende Listen (wenn Zugriffshäufigkeiten für die einzelnen Elemente nicht bekannt) Frequency count Transpose Move-to-Front

12 G.Heyer Algorithmen und Datenstrukturen 12 Skip-Listen Wörterbücher (Dictionaries): Mengen von Elementen eines Grundtyps mit Operationen Suchen, Einfügen, Entfernen. Wörterbuchproblem: Finden geeigneter Datenstruktur und effizienter Algorithmen für diese Operationen (Listen eine von mehreren Realisierungsmöglichkeiten). Skip-Listen: Effiziente Realisierungsmöglichkeit. a) Perfekte Skip-Listen Def.: Eine perfekte Skip-Liste ist eine sortierte, verkettete lineare Liste, mit Kopf und Endelement, wobei gilt: 1) jedes 2 i -te Element hat Zeiger auf das 2 i Positionen weiter rechts stehendes Element. 2) Endelement hat Wert unendlich.

13 G.Heyer Algorithmen und Datenstrukturen 13 Jedes Listenelement hat Zeiger auf nächstes Element. Jedes 2. Listenelement hat Zeiger auf übernächstes Element. Jedes 4. Listenelement hat Zeiger auf 4 Positionen weiter rechts stehendes Element, etc. Gesamtzahl der nötigen Zeiger für Länge N: N + N/2 + N/ N Höhe eines Elements: Anzahl der Zeiger des Elements -1. Höhe der Liste (L.höhe): maximale Zeigeranzahl eines Elements - 1: |_ log N _|.

14 G.Heyer Algorithmen und Datenstrukturen 14 Suchen informell: 1. Sei i die Höhe der Skip-Liste, der Kopf der Liste das aktuell inspizierte Objekt. 2. Falls Schlüssel des Objekts, auf das der Niveau-i-Zeiger des aktuellen Objekts zeigt, kleiner als der Suchschlüssel ist, mache dieses zum aktuellen Objekt. 3. dekrementiere i. Falls i >= 0 gehe nach Falls der Schlüssel des Nachfolgers des aktuellen Objekts identisch mit dem Suchschlüssel ist, gib Nachfolger aus, sonst ist Objekt mit Suchschlüssel nicht in Liste.

15 G.Heyer Algorithmen und Datenstrukturen 15 Suchaufwand Suchen in perfekten Skip-Listen ist O(log N). Problem: Einfügen und Löschen führt zu erheblichem Mehraufwand, wenn Skip-Listen perfekt bleiben sollen. Deshalb: randomisierte SLs: Man sorgt dafür, daß die Anzahl der vorkommenden Höhen stimmt (d.h. Hälfte Niveau 1 Zeiger, Viertel Niveau 2 Zeiger etc.). Neues Element erhält Höhe i mit Wahrscheinlichkeit 1 / 2 i+1, 0 i maxhöhe Beim Einfügen (und Entfernen) müssen Zeiger entsprechend der zufälligen Höhe des Elements umgesetzt werden.

16 G.Heyer Algorithmen und Datenstrukturen 16 Komplexitätsanalyse (etwas aufwendiger Beweis) zeigt: Erwartungswert (aber nicht worst case) für Kosten von Suchen, Einfügen und Entfernen in randomisierten Skip-Listen ist immer noch O(log N).


Herunterladen ppt "G.Heyer Algorithmen und Datenstrukturen 1 Kapitel 3: Listen Lineare Liste: endliche Folge von Elementen eines Grundtyps (n>=0), leere Liste <> falls n=0."

Ähnliche Präsentationen


Google-Anzeigen