80
Dynamisches Array als "verkettete Liste"

Dynamisches Array als "verkettete Liste"

Embed Size (px)

DESCRIPTION

Dynamisches Array als "verkettete Liste". Ein Vergleich. Durch die intensive Nutzung jeden Quadratmeters Bodenfläche (Hausbau und Tomatenplantagen) gibt es in Amsterdam keine Möglichkeit mehr eine freie Bodenfläche zu finden. - PowerPoint PPT Presentation

Citation preview

Page 1: Dynamisches Array als  "verkettete Liste"

Dynamisches Array als

"verkettete Liste"

Page 2: Dynamisches Array als  "verkettete Liste"

Ein Vergleich

Page 3: Dynamisches Array als  "verkettete Liste"

Durch die intensive Nutzung jeden Quadratmeters Bodenfläche (Hausbau und Tomatenplantagen) gibt es in Amsterdam keine Möglichkeit mehr eine freie Bodenfläche zu finden.

Page 4: Dynamisches Array als  "verkettete Liste"

Deswegen wird mittlerweile eine neue Bebauungsfläche genutzt: das Wasser in den Kanälen. Diese neue genutzte Fläche wird mit Hausbooten versehen.

Page 5: Dynamisches Array als  "verkettete Liste"

X Land (Bootsteg mit nur einem Anlegepunkt)

Das Boot muss mit dem Land verbunden werden.

Wie wird dieses Boot mit dem Land verbunden, obwohl der Anlegepunkt belegt ist?

Wie wird dieses Boot mit dem Land verbunden, obwohl der Anlegepunkt belegt ist?

Page 6: Dynamisches Array als  "verkettete Liste"

Bevor wir uns zu lange in Holland aufhalten - und dabei die Tomatenbauern bei ihrer wichtigen Arbeit stören – und bevor sich unser neu erworbenes Wissen in Rauch auflöst, schnell noch ein anderer Vergleich...

Page 7: Dynamisches Array als  "verkettete Liste"

In der Klasse wurde ausgemacht: Wenn jemand ein wichtiges Ereignis erfährt (wie z.B. nächste Kurzarbeit im Mathe), sollen alle Schüler der Klasse benachrichtigt werden. Wie kann man dies realisieren, ohne daß ein Schüler alle anderen anruft bzw. jeder Schüler daran beteiligt wird ?

Page 8: Dynamisches Array als  "verkettete Liste"

Durch eine Telefonkette benachrichtigen sich die Schüler Gustav, Olaf, Miroslav, Wiglaf und Stanislav der KlasseName ruft an

Gustav Olaf

Olaf Miroslav

Miroslav Wiglaf

Wiglaf Stanislav

Stanislav ????????

Page 9: Dynamisches Array als  "verkettete Liste"

Wen soll Stanislav anrufen?

Name ruft an

Gustav Olaf

Olaf Miroslav

Miroslav Wiglaf

Wiglaf Stanislav

Stanislav

Page 10: Dynamisches Array als  "verkettete Liste"

Niemandem mehr, oder …

Name ruft an

Gustav Olaf

Olaf Miroslav

Miroslav Wiglaf

Wiglaf Stanislav

Stanislav

Page 11: Dynamisches Array als  "verkettete Liste"

Gustav, dann hat man einen Telefonring

Name ruft an

Gustav Olaf

Olaf Miroslav

Miroslav Wiglaf

Wiglaf Stanislav

Stanislav

Page 12: Dynamisches Array als  "verkettete Liste"

Von Holland, Ketten und Ringen zurück zur EDV nach Deutschland...

Page 13: Dynamisches Array als  "verkettete Liste"

Warum kann man nicht beliebig viele Zahlen immer wieder hintereinander in einem Array anfügen?

Page 14: Dynamisches Array als  "verkettete Liste"

Weil ein Array eine feste Länge haben muss.

Page 15: Dynamisches Array als  "verkettete Liste"

Was müsste man also bei jedem Anfügevorgang machen?

Page 16: Dynamisches Array als  "verkettete Liste"

dynamischen Speicher reservieren!

Page 17: Dynamisches Array als  "verkettete Liste"

Beispiel:

Page 18: Dynamisches Array als  "verkettete Liste"

Annahme: Man will hintereinander die folgenden Zahlen abspeichern:

-93 , 71 , 19

Man reserviert also dynamisch (d.h.während der Laufzeit) Speicher für eine Zahl, dann Speicher für die nächste Zahl, usw.Die reservierten Speicher (mit den Adressen) liefert jeweils das Betriebssystem.

19

-93

71

...

...0911

...

...

0345...

...0007

...

...

Page 19: Dynamisches Array als  "verkettete Liste"

Welches Problem hat man, wenn man diese Zahlen (in der Reihenfolge wie sie abgelegt wurden) auf dem Bildschirm ausgeben will

Man kennt nicht die Adressen dieser Zahlen, weil diese Adressen nicht gespeichert wurden.

Was muss man also machen, um diese Zahlen ausgeben zu können?

-93

71

19

...

...0911

...

...

0345...

...0007

...

...

Page 20: Dynamisches Array als  "verkettete Liste"

-93

71

19

...

...0911

...

...

0345...

...0007

...

... Man muss jeweils neben der Zahl auch die Adresse der nächsten Zahl speichern.

Man braucht also einen Datentyp, in dem neben einer Zahl eine Adresse gespeichert wird.

dtelement Zahl Adresse

Wir nennen den Datentyp hier "dtelement" und stellen dies schematisch wie folgt dar:

Page 21: Dynamisches Array als  "verkettete Liste"

Wie sieht dann die Verlinkung dieser Speicherblöcke mit dem Datentyp element aus?(-93 , 71 , 19)Schreiben Sie die 3 Speicherblöcke auf und verlinken sie

71

-93

19

...

...0911

...

...

0345...

...0007

...

...

Page 22: Dynamisches Array als  "verkettete Liste"

71

-93

19

-930911

19 ?

71 0007

Welche Adresse soll hier eingetragen werden und ...

...wie kann man dieses Element als das Letzte markieren?

...

...0911

...

...

0345...

...0007

...

...

Page 23: Dynamisches Array als  "verkettete Liste"

71

-93

19

...

...0911

...

...

0345...

...0007

...

... -930911

19 71 0007

Page 24: Dynamisches Array als  "verkettete Liste"

71

-93

19

...

...0911

...

...

0345...

...0007

...

... -930911

19 NULL

71 0007

NULL ist eine spezielle Adresse, die z.B. für diesen Zweck verwendet werden kann.

Page 25: Dynamisches Array als  "verkettete Liste"

71

-93

19NULL

...

...0911

...

...

0345...

...0007

...

...

0911

0007

Wie sieht die genaue Belegung im Arbeitsspeicher aus?Der Speicherblock (Zahl, Adresse), der –93 in das dynamische Array einträgt, soll abgespeichert werden.

Was fehlt noch?

71 soll angefügt werden.

19 soll angefügt werden.

Man hat also mit dem 1. Element das ganze dynamische Array als sogenannte "verkettete Liste".

Page 26: Dynamisches Array als  "verkettete Liste"

Umsetzung in C:

Page 27: Dynamisches Array als  "verkettete Liste"

#include "stdafx.h"#include <stdio.h>#include <malloc.h>

struct dtelement{ int zahl; struct dtelement *next;};

int main(){ ...}

Name der Struktur(frei wählbar)

Name der Adresse (frei wählbar)

Diese Adresse muss wieder auf eine Variable zeigen, die den Datentyp dtelement hat!

Page 28: Dynamisches Array als  "verkettete Liste"

Reservieren Sie jeweils für die Zahl 10 und 20 dynamisch Speicher und verlinken diese Speicherplätze dann miteinander. Geben Sie anschließend - vom Anfang der verketteten Liste ausgehend - die Zahlen auf dem Bildschirm aus.

Page 29: Dynamisches Array als  "verkettete Liste"

int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement));

?anf

?e Annahme:Die Variablen anf und e werden an der Adresse 0050 und 0060 gespeichert.

Welchen Wert hat anf und e an dieser Stelle ?

0050

0060

Page 30: Dynamisches Array als  "verkettete Liste"

int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement));

Welchen Wert hat anf und e an dieser Stelle ? (also nach e = ...

Annahme:Der 1. reservierte Speicher beginnt bei der Adresse 0100, Der 2. reservierte Speicher beginnt bei der Adresse 0200.

?anf

?e

0050

0060

Page 31: Dynamisches Array als  "verkettete Liste"

int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement));

0100

0200e

0050

0060

Wie werden die einzelnen Bereiche des Speichers an der Adresse 0100 (bzw. 0200) interpretiert bzw. was bedeuten sie?

... 0200 ... ... 0100

Eine Integer-Zahl

Eine Adresse, die als Datentyp die Struktur dtelement hat.

Eine Integer-Zahl

Eine Adresse, die als Datentyp die Struktur dtelement hat.

anf

Page 32: Dynamisches Array als  "verkettete Liste"

int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement));

0100anf

0200e

... 0200 ... ... 0100

Welche Werte stehen an diesen 4 Stellen?

0050

0060

Page 33: Dynamisches Array als  "verkettete Liste"

int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement));

0100

0200e

... 0200 ... ... 0100 ?

?

??

0050

0060

anf

Page 34: Dynamisches Array als  "verkettete Liste"

int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement));

0100

0200e

... 0200 ... ... 0100 ?

?

??

0050

0060

Programm geht gleich weiter...

Durch welche Anweisungen wird im 1. reservierten Speicher die Zahl 10 und im 2. reservierten Speicher die Zahl 20 abgespeichert?

anf

Page 35: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100 ?

?

??

0100* .zahl

anf

Page 36: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

??

0100* .zahl

anf

Page 37: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

??

10

0100* .zahl

anf

Page 38: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

??

10

(*e).zahl = 20;

0200* .zahl

anf

Page 39: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

?

10

(*e).zahl = 20;

0200* .zahl

anf

Page 40: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

?

10

(*e).zahl = 20;

20

Durch welche Anweisung wird der 1. reservierte Speicher mit dem 2. reservierten Speicher verlinkt?

0200* .zahl

anf

Page 41: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

?

10

(*e).zahl = 20;

20

(*anf).next = e;

0200

0100* .next

anf

Page 42: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

10

(*e).zahl = 20;

20

(*anf).next = e;

0200

0100* .next

anf

Page 43: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

10

(*e).zahl = 20;

20

(*anf).next = e;

0200

0200

0100* .next

anf

Page 44: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100

?

10

(*e).zahl = 20;

20

(*anf).next = e;

0200

Durch welche Anweisung kann man das 2. angefügte element als das Letzte markieren?(*e).next = NULL;

0200* .next

anf

Page 45: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100 10

(*e).zahl = 20;

20

(*anf).next = e;

0200

Durch welche Anweisung kann man das 2. angefügte element als das Letzte markieren?(*e).next = NULL;

0200* .next

anf

Page 46: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100 10

(*e).zahl = 20;

20

(*anf).next = e;

0200

Durch welche Anweisung kann man das 2. angefügte element als das Letzte markieren?(*e).next = NULL;

0200* .next

NULL

anf

Page 47: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*anf).zahl = 10;

... 0200 ... ... 0100 10

(*e).zahl = 20;

20

(*anf).next = e;

0200

Damit hat man folgende Verlinkung der Elemente im Arbeitsspeicher(*e).next = NULL;

NULL

return 0;}

anf

In anf (wie Anfang) ist die Adresse des 1. Elements gespeichert. Damit kann man die Liste durchlaufen. In e wird die Adresse eines neu anzufügenden Elements zwischengespeichert und dann in die Liste eingetragen (als Link auf das neue Element).

Page 48: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*(*anf).next).zahl = 30;

... 0200 ... ... 0100 10

20

0200

NULL

anf

Was würde folgende zusätzliche Anweisung

im Speicher veranlassen?

...

0100* .next

0200* .zahl

Page 49: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*(*anf).next).zahl = 30;

... 0200 ... ... 0100 10

0200

NULL

anf

Was würde folgende zusätzliche Anweisung

im Speicher veranlassen?

...

0100* .next

0200* .zahl

Page 50: Dynamisches Array als  "verkettete Liste"

0100

0200e

0050

0060

(*(*anf).next).zahl = 30;

... 0200 ... ... 0100 10

30

0200

NULL

anf

Was würde folgende zusätzliche Anweisung

im Speicher veranlassen?

...

0100* .next

0200* .zahl

Page 51: Dynamisches Array als  "verkettete Liste"

Aufgabe:Erstellen Sie die folgenden

Funktionen ...

Page 52: Dynamisches Array als  "verkettete Liste"

struct dtelement *anfuegen(struct dtelement *dynArray, int wert) Beschreibung:fügt an ein dynamisches Array (verkettete Liste) eine Zahl an.Gibt Adresse des (letzten) neu angefügten Elements zurück. dynArray ist die Adresse des letzten Elements

Page 53: Dynamisches Array als  "verkettete Liste"

#include "stdafx.h"#include <stdio.h>#include <malloc.h>

struct element{ int zahl; struct element *next;};struct element *anfuegen( struct element *dynArray, int wert);

Page 54: Dynamisches Array als  "verkettete Liste"

int main(){ struct element* dynArray; struct element *anfang; dynArray = anfuegen(NULL, 9); anfang = dynArray; dynArray = anfuegen(dynArray, 5); dynArray = anfuegen(dynArray, 13);

return 0;}

Page 55: Dynamisches Array als  "verkettete Liste"

struct element *anfuegen( struct element *dynArray, int wert){ struct element *kg;

kg bedeutet Kettenglied. In Ihrem Quellcode bitte Variable mit

kettenglied bezeichnen

Page 56: Dynamisches Array als  "verkettete Liste"

struct element *anfuegen( struct element *dynArray, int wert){ struct element *kg; if(dynArray == NULL){

NULL bedeutet: es existiert noch keine verkettete Liste, also muß der folgende

Speicherblock erzeugt werden.Dieser ist die dynamische Liste.

wertNULL

Page 57: Dynamisches Array als  "verkettete Liste"

struct element *anfuegen( struct element *dynArray, int wert){ struct element *kg; if(dynArray == NULL){ kg=(struct element*)malloc( sizeof(struct element));

Hole Speicher für ein neues Element und speichere die Anfangsadresse des Speichers in kg

Page 58: Dynamisches Array als  "verkettete Liste"

struct element *anfuegen( struct element *dynArray, int wert){ struct element *kg; if(dynArray == NULL){ kg=(struct element*)malloc( sizeof(struct element)); (*kg).zahl = wert;

Trage den Wert in das dynamische Array ein

Page 59: Dynamisches Array als  "verkettete Liste"

struct element *anfuegen( struct element *dynArray, int wert){ struct element *kg; if(dynArray == NULL){ kg=(struct element*)malloc( sizeof(struct element)); (*kg).zahl = wert; (*kg).next = NULL;

Trage das letzte Element des dynamischen Arrays ein

Page 60: Dynamisches Array als  "verkettete Liste"

struct element *anfuegen( struct element *dynArray, int wert){ struct element *kg; if(dynArray == NULL){ kg=(struct element*)malloc( sizeof(struct element)); (*kg).zahl = wert; (*kg).next = NULL; return kg; }

Gib dieses Element zurück

Page 61: Dynamisches Array als  "verkettete Liste"

else{verkettete Liste existiert schon (wir nehmen

hier an, daß sie aus 2 Elementen besteht).Dann muß ein Element angefügt werden…

wert10911

wert3 NULL

wert2 Null

Da es jetzt das letzte Element ist, wird es mit NULL bestückt und es muß noch mit der aktuellen verkettenen Liste verbunden werden. Was ist zu tun ?

Page 62: Dynamisches Array als  "verkettete Liste"

else{verkettete Liste existiert schon (wir nehmen

hier an, daß sie aus 2 Elementen besteht).Dann muß ein Element angefügt werden…

wert10911

wert3 NULL

wert2

Da es jetzt das letzte Element ist, wird es mit NULL bestückt und es muß noch mit der aktuellen verkettenen Liste verbunden werden. Was ist zu tun ?

In die Schublade ADSRESSE des zweiten Speicherblocks die Adresse des neu anzufügenden Elements eintragen!

Adresse des Speicherblocks, der den Wert wert3 hat eintragen

Page 63: Dynamisches Array als  "verkettete Liste"

else{ kg=(struct element*)malloc( sizeof(structelement));

Hole Speicher für ein neues Element und speichere die Anfangsadresse des Speichers in kg

Page 64: Dynamisches Array als  "verkettete Liste"

else{ kg=(struct element*)malloc( sizeof(structelement)); (*kg).zahl = wert; (*kg).next = NULL;

Bestücke das Kettenglied mit den entsprechenden Werten

Page 65: Dynamisches Array als  "verkettete Liste"

else{ kg=(struct element*)malloc( sizeof(structelement)); (*kg).zahl = wert; (*kg).next = NULL; (*dynArray).next=kg;

Verknüpfe das Kettenglied mit dem dynamischen Array

Page 66: Dynamisches Array als  "verkettete Liste"

else{ kg=(struct element*)malloc( sizeof(structelement)); (*kg).zahl = wert; (*kg).next = NULL; (*dynArray).next=kg; return kg; }} Gib das Kettenglied zurück

Page 67: Dynamisches Array als  "verkettete Liste"

Weiter mit den Funktionen,die Sie nun implementieren müssen:

Page 68: Dynamisches Array als  "verkettete Liste"

void printList(struct dtelement *dynArray) Beschreibung:gibt ein dynamisches Array (verkettete Liste) auf dem Bildschirm aus.

Page 69: Dynamisches Array als  "verkettete Liste"

void delList (struct dtelement *dynArray) Beschreibung:löscht das ganze dynamische Array (verkettete Liste).

void delElement (struct dtelement *element) Beschreibung:löscht ein Element des dynamischen Arrays (verkettete Liste).

Page 70: Dynamisches Array als  "verkettete Liste"

Bemerkungen zur Funktion:void delElement (struct dtelement *element)

Beispiel:Das Element mit der Adresse 0070 soll aus der Liste gelöscht werden.Also...

Page 71: Dynamisches Array als  "verkettete Liste"

100070

0050

0060

300090

0070

0080

20NULL

0090

0100

Dieses komplette Element soll gelöscht werden. Reicht es aus, diesen Speicherbereich mit free freizugeben ?Also ...

Page 72: Dynamisches Array als  "verkettete Liste"

100070

0050

0060

20NULL

0090

0100

Welche Probleme gibt es jetzt ?

Die Verlinkung stimmt nicht mehr! Das Element, das die Zahl 10 enthält, zeigt nicht mehr auf das Element, das die Zahl 20 enthält. Also ...

Page 73: Dynamisches Array als  "verkettete Liste"

100070

0050

0060

300090

0070

0080

20NULL

0090

0100

Was muss also noch gemacht werden?

Von diesem Element muss die Adresse des Vorgängers und die Adresse des Nachfolgers ermittelt werden und dann der Vorgänger mit dem Nachfolger verlinkt werden. Dann muss das Element gelöscht werden.

Page 74: Dynamisches Array als  "verkettete Liste"

100070

0050

0060

300090

0070

0080

20NULL

0090

0100

Von diesem Element muss die Adresse des Vorgängers und die Adresse des Nachfolgers ermittelt werden und dann der Vorgänger mit dem Nachfolger verlinkt werden. Dann muss das Element gelöscht werden.

Was muss also noch gemacht werden?

Page 75: Dynamisches Array als  "verkettete Liste"

100050

0060

300090

0070

0080

20NULL

0090

0100

Was muss also noch gemacht werden?

Von diesem Element muss die Adresse des Vorgängers und die Adresse des Nachfolgers ermittelt werden und dann der Vorgänger mit dem Nachfolger verlinkt werden. Dann muss das Element gelöscht werden.

Page 76: Dynamisches Array als  "verkettete Liste"

100090

0050

0060

300090

0070

0080

20NULL

0090

0100

Was muss also noch gemacht werden?

Von diesem Element muss die Adresse des Vorgängers und die Adresse des Nachfolgers ermittelt werden und dann der Vorgänger mit dem Nachfolger verlinkt werden. Dann muss das Element gelöscht werden.

Page 77: Dynamisches Array als  "verkettete Liste"

100090

0050

0060

20NULL

0090

0100

Was muss also noch gemacht werden?

Page 78: Dynamisches Array als  "verkettete Liste"

100090

0050

0060

20NULL

0090

0100

Wie kann die Adresse des Vorgängers ermittelt werden?

Indem man z.B. in der Liste in jedem Element nicht nur die Adresse des Nachfolgers, sondern auch die des Vorgängers speichert (dies heißt eine doppelt verkettete Liste).

Page 79: Dynamisches Array als  "verkettete Liste"

100090

0050

0060

20NULL

0090

0100

Gibt es auch noch eine andere Lösung?

Man gibt in der Funktion als Parameter nicht die Adresse des zu löschenden Elements an, sondern ....

die Adresse des Vorgängers des zu löschenden Elements ...

dann kann in der Funktion die Adresse des Nachfolgers und des Nach-Nachfolgers ermittelt werden und die Liste muss nur einfach verkettet sein (nur jeweiligen Nachfolger eines Elements speichern).

Page 80: Dynamisches Array als  "verkettete Liste"

Welches Element der Liste könnte dann aber nicht gelöscht werden?Warum?

Das 1. Element könnte nicht gelöscht werden, weil es keinen Vorgänger hat.

Wie könnte man dies trotzdem noch erreichen?

In dem man die Parameterliste um einen Parameter erweitert. In diesem wird angegeben, ob das 1. Element gelöscht werden soll oder nicht.