Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Dynamisches Array als "verkettete Liste". Ein Vergleich.

Ähnliche Präsentationen


Präsentation zum Thema: "Dynamisches Array als "verkettete Liste". Ein Vergleich."—  Präsentation transkript:

1 Dynamisches Array als "verkettete Liste"

2 Ein Vergleich

3 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.

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

5 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?

6 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...

7 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 ?

8 Durch eine Telefonkette benachrichtigen sich die Schüler Gustav, Olaf, Miroslav, Wiglaf und Stanislav der Klasse Nameruft an GustavOlaf Miroslav Wiglaf Stanislav ????????

9 Wen soll Stanislav anrufen? Nameruft an GustavOlaf Miroslav Wiglaf Stanislav

10 Niemandem mehr, oder … Nameruft an GustavOlaf Miroslav Wiglaf Stanislav

11 Gustav, dann hat man einen Telefonring Nameruft an GustavOlaf Miroslav Wiglaf Stanislav

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

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

14 Weil ein Array eine feste Länge haben muss.

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

16 dynamischen Speicher reservieren!

17 Beispiel:

18 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...

19 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...

20 -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:

21 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...

22 71 -93 19 -93 0911 19 ? 71 0007 Welche Adresse soll hier eingetragen werden und......wie kann man dieses Element als das Letzte markieren?... 0911... 0345... 0007...

23 71 -93 19... 0911... 0345... 0007... -93 0911 19 71 0007

24 71 -93 19... 0911... 0345... 0007... -93 0911 19 NULL 71 0007 NULL ist eine spezielle Adresse, die z.B. für diesen Zweck verwendet werden kann.

25 71 -93 19 NULL... 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".

26 Umsetzung in C:

27 #include "stdafx.h" #include 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!

28 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.

29 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

30 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

31 int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement)); 0100 0200 e 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

32 int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement)); 0100 anf 0200 e... 0200... 0100 Welche Werte stehen an diesen 4 Stellen? 0050 0060

33 int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement)); 0100 0200 e... 0200... 0100 ? ? ? ? 0050 0060 anf

34 int main(){ struct dtelement *anf; struct dtelement *e; anf = (struct dtelement *) malloc(sizeof( struct dtelement)); e = (struct dtelement *) malloc(sizeof( struct dtelement)); 0100 0200 e... 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

35 0100 0200 e 0050 0060 (*anf).zahl = 10;... 0200... 0100 ? ? ? ? *.zahl anf

36 0100 0200 e 0050 0060 (*anf).zahl = 10;... 0200... 0100 ? ? ? *.zahl anf

37 0100 0200 e 0050 0060 (*anf).zahl = 10;... 0200... 0100 ? ? ? 10 0100*.zahl anf

38 0100 0200 e 0050 0060 (*anf).zahl = 10;... 0200... 0100 ? ? ? 10 (*e).zahl = 20; 0200*.zahl anf

39 0100 0200 e 0050 0060 (*anf).zahl = 10;... 0200... 0100 ? ? 10 (*e).zahl = 20; 0200*.zahl anf

40 0100 0200 e 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

41 0100 0200 e 0050 0060 (*anf).zahl = 10;... 0200... 0100 ? ? 10 (*e).zahl = 20; 20 (*anf).next = e; 0200 0100*.next anf

42 0100 0200 e 0050 0060 (*anf).zahl = 10;... 0200... 0100 ? 10 (*e).zahl = 20; 20 (*anf).next = e; 0200 0100*.next anf

43 0100 0200 e 0050 0060 (*anf).zahl = 10;... 0200... 0100 ? 10 (*e).zahl = 20; 20 (*anf).next = e; 0200 0100*.next anf

44 0100 0200 e 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

45 0100 0200 e 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

46 0100 0200 e 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

47 0100 0200 e 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).

48 0100 0200 e 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

49 0100 0200 e 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

50 0100 0200 e 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

51 Aufgabe: Erstellen Sie die folgenden Funktionen...

52 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

53 #include "stdafx.h" #include #include struct element{ int zahl; struct element *next; }; struct element *anfuegen( struct element *dynArray, int wert);

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

55 struct element *anfuegen( struct element *dynArray, int wert){ struct element *kg; kg bedeutet Kettenglied. In Ihrem Quellcode bitte Variable mit kettenglied bezeichnen

56 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. wert NULL

57 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

58 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

59 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

60 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

61 else{ verkettete Liste existiert schon (wir nehmen hier an, daß sie aus 2 Elementen besteht). Dann muß ein Element angefügt werden… wert1 0911 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 ?

62 else{ verkettete Liste existiert schon (wir nehmen hier an, daß sie aus 2 Elementen besteht). Dann muß ein Element angefügt werden… wert1 0911 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

63 else{ kg=(struct element*)malloc( sizeof(structelement)); Hole Speicher für ein neues Element und speichere die Anfangsadresse des Speichers in kg

64 else{ kg=(struct element*)malloc( sizeof(structelement)); (*kg).zahl = wert; (*kg).next = NULL; Bestücke das Kettenglied mit den entsprechenden Werten

65 else{ kg=(struct element*)malloc( sizeof(structelement)); (*kg).zahl = wert; (*kg).next = NULL; (*dynArray).next=kg; Verknüpfe das Kettenglied mit dem dynamischen Array

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

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

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

69 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).

70 Bemerkungen zur Funktion: void delElement (struct dtelement *element) Beispiel: Das Element mit der Adresse 0070 soll aus der Liste gelöscht werden. Also...

71 10 0070 0050 0060 30 0090 0070 0080 20 NULL 0090 0100 Dieses komplette Element soll gelöscht werden. Reicht es aus, diesen Speicherbereich mit free freizugeben ? Also...

72 10 0070 0050 0060 20 NULL 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...

73 10 0070 0050 0060 30 0090 0070 0080 20 NULL 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.

74 10 0070 0050 0060 30 0090 0070 0080 20 NULL 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?

75 10 0050 0060 30 0090 0070 0080 20 NULL 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.

76 10 0090 0050 0060 30 0090 0070 0080 20 NULL 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.

77 10 0090 0050 0060 20 NULL 0090 0100 Was muss also noch gemacht werden?

78 10 0090 0050 0060 20 NULL 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).

79 10 0090 0050 0060 20 NULL 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).

80 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.


Herunterladen ppt "Dynamisches Array als "verkettete Liste". Ein Vergleich."

Ähnliche Präsentationen


Google-Anzeigen