Slides:



Advertisements
Ähnliche Präsentationen
Ziele von EINI I + II Einführen in „Informatik“
Advertisements

Klassen - Verkettete Liste -
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (26-Graphenalgorithmen: Wiederholung und Übung) Prof. Th. Ottmann.
Informatik II – Kapitel 11
Sortieren I - Bubblesort -
Kapitel 3: Listen Lineare Liste: endliche Folge von Elementen eines Grundtyps (n>=0), leere Liste falls n=0 Listenelemente besitzen.
Programmieren 2 Future Car Projekt Praktikum 6
Java: Dynamische Datentypen
Listen Richard Göbel.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (13 – Offenes Hashing) Prof. Th. Ottmann.
Algorithmen und Datenstrukturen
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (06 - Anwendungen von Stapeln und Schlangen) Prof. Th. Ottmann.
Anwendungen von Stapeln und Schlangen
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (21 – Kürzeste Wege) T. Lauer.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (12 – Dynamische Tabellen) Prof. Th. Ottmann.
Informatik II, SS 2008 Algorithmen und Datenstrukturen Vorlesung 13 Prof. Dr. Thomas Ottmann Algorithmen & Datenstrukturen, Institut für Informatik Fakultät.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (07 - Skiplisten) Prof. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (05 – Elementare Datenstrukturen) Prof. Th. Ottmann.
Informatik II, SS 2008 Algorithmen und Datenstrukturen Vorlesung 6 Prof. Dr. Thomas Ottmann Algorithmen & Datenstrukturen, Institut für Informatik Fakultät.
Kapitel 3 Elementare Datenstrukturen TexPoint fonts used in EMF.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 7 Claudio Moraga, Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.
Operationen auf verketteten Listen
Diskrete Mathematik I Vorlesung 6 Binärer Suchbaum II.
Institut für Kartographie und Geoinformation Prof. Dr. Lutz Plümer Diskrete Mathematik I Vorlesung Listen-
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
Die Methode public Knoten einfuegenVor (Datenelement dNeu, Datenelement dVergleich) public Knoten einfuegenVor(Datenelement dNeu, Datenelement dVergleich){
Mergesort Divide and Conquer
Einfach verkettete Listen
Einfach verkettete Listen (OOP)
PRJ 2007/1 Stefan Dissmann Verkettete datenstruktur: Liste Problem: Liste, die eine beliebige Zahl von Elementen verwaltet Operationen: Erzeugen, Anfügen,
Rekursion mit Listen: Quicksort
Abteilung für Telekooperation Übung Softwareentwicklung 1 für Wirtschaftsinformatik Dr. Wieland Schwinger
Abteilung für Telekooperation Übung Softwareentwicklung 1 für Wirtschaftsinformatik Dr. Wieland Schwinger
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung
1. Die rekursive Datenstruktur Liste 1.1 Warteschlange (Queue)
Efficient Alias Set Analysis Using SSA Form Proseminar Programmanalyse WS 11/12 André Hunke.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fakultät.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung
Einführung in die Programmiersprache C 4
1.2 Trennung von Struktur und Inhalt
1.6 Die Datenstruktur Stapel Ein Stapel (Stack) ist ein Sonderfall einer Liste. Die Elemente werden nach dem Prinzip LIFO (Last In First Out) angefügt.
Einfach und doppelt verkettete Listen in JAVA by Jens Weibler
Algorithmen und Datenstrukturen Übungsmodul 8
Programmieren in C Dynamische Listen / Bäume
Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Thomas Hilpold: Algorithmen und Datenstrukturen SS 2005 Mag.Th. Hilpold u. Dr. A.Stritzinger.
Informatik Datenstruktur Graph 3.3 Durchlaufen von Graphen
SWE1 / Übung 10 ( ) Rekursion Binärbäume.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Sortieralgorithmen Greedy Sortieren: Sortieren durch Auswahl, Einfügen und Austauschen Divide-and-Conquer-Sortieren: Quicksort und merge sort Foliensatz.
Informatik Beschreibung von Abläufen durch Algorithmen 3.3 Wiederholugnsanweisungen 3. Beschreibung von Abläufen durch Algorithmen 3.3 Wiederholungsanweisungen.
Mag. Thomas Hilpold, Universität Linz, Institut für Wirtschaftsinformatik – Software Engineering 1 Algorithmen und Datenstrukturen 1 SS 2002 Mag.Thomas.
Algorithmen und Datenstrukturen 1 SS 2002
1 // Verkettete Liste 3 // demonstriert verkettete Listen und // Rekursion // (mit Entfernen eines Listenelementes) // #include struct Liste { int Element;
M a r c – o l i v e r p a h l Informatik II – Kapitel 12 „Sortier-Algorithmen“ Zusammenfassung des Kapitel 12 Küchlin, Weber, Einführung in die Informatik,
Mag. Thomas Hilpold, Universität Linz, Institut für Wirtschaftsinformatik – Software Engineering 1 Algorithmen und Datenstrukturen 1 SS 2002 Mag.Thomas.
Diskrete Mathe Diskrete Mathematik I Listen Vorlesung 4.
1 // Verkettete Liste 2 // demonstriert verkettete Listen und // Rekursion // (Einfügen am "Fuß") // #include struct Liste { int Element; Liste *weiter;
Dr. Wolfram Amme, Generisches Programmieren, Informatik II, FSU Jena, SS Generisches Programmieren.
Praktische Informatik 1
1. Die rekursive Datenstruktur Liste 1.5 Das Entwurfsmuster Kompositum
Arrays of Objects, a 3 part process
1. Die rekursive Datenstruktur Liste 1
 Präsentation transkript:

3.3 Verkettete Listen Erweiterung der (nicht-leeren!) Liste: tmp = head; while (tmp.next != null) tmp = tmp.next; tmp.next = new ListNode(4); tmp 4 null tmp tmp tmp head null 1 2 3 Will man schließlich ein neues Element an das Ende der Liste anhängen, so muß man zunächst das Ende der Liste aufsuchen: …

3.3 Verkettete Listen Entfernen des letzten Elementes aus der (aus mehr als 1 Element bestehenden!) Liste: ListNode<Integer> pred = null; tmp = head; while (tmp.next != null) { pred = tmp; tmp = tmp.next; } pred.next = null; tmp pred null pred pred pred pred null tmp tmp tmp tmp head null 1 2 3 4 null Eine etwas 'knifflige' Operation bei dieser Repräsentation als einfach vorwärts-verkettete Liste ist das Entfernen des letzten Elements: …

3.3 Verkettete Listen Rekursive Traversierung einer Liste vom Anfang zum Ende und wieder zurück: void traverse(ListNode<E> p) { ListNode<Integer> Node; if (Node = p; p != null; Node = Node.next) { process(Node.data); } } initialer Aufruf: traverse(head); Will man die Liste vom ersten bis zum letzten Knoten und wieder zurück zum ersten Knoten traversieren, so kann man dies durch folgende rekursive Methode realisieren: …

3.3 Verkettete Listen old null present Iterative Traversierung der Liste vom Anfang zum Ende und wieder zurück: ListNode<E> head, tmp; … ListNode<E> old, present; present = head; for (int i = 1; i <= 2; i++) { old = null; while (present != null) { process(present.data); tmp = present.next; present.next = old; old = present; present = tmp; } present = old; } head null null present old old present present old present old present old old present present old present old old present present old old present Will man aber nicht den zusätzlichen Speicherplatz investieren, der für die rekursiven Aufrufe notwendig ist, so kann man diese Traversierung auch folgendermaßen iterativ implementieren: … Am besten kann man sich die beiden Zeiger present und old als die Zinken einer Gabel vorstellen, die über die Knoten bewegt wird und die Verbindung zwischen einem Knoten und seinem Vorgänger sicherstellt. Unschön ist hierbei vom Programmcode her die for-Schleife, die zweimal durchlaufen wird. Diese for-Schleife läßt sich vermeiden, wenn man den folgenden Trick benutzt. Bewirkt eine Listenumkehr

3.3 Verkettete Listen Programmcode für iterative Traversierung der Liste vom Anfang zum Ende und wieder zurück wird eleganter, wenn der letzte Knoten nicht auf null, sondern auf sich selbst verweist: head ListNode<E> head, tmp; … ListNode<E> old, present; present = head; old = null; while (present != null) { process(present.data); tmp = present.next; present.next = old; old = present; present = tmp; } Der letzte Knoten der Liste verweist nicht auf null, sondern auf sich selbst. Dann sieht der Programmcode für die iterative Traversierung folgendermaßen aus: …

3.3 Verkettete Listen Erweiterungen: Zirkuläre Listen: entry e1 e2 ... Eine lineare Liste ist manchmal handlicher zu benutzen, wenn der Schwanz auf den Kopf der Liste zurückverweist, wodurch eine zirkuläre Liste entsteht. In einer zirkulären Liste werden der Anfangsknoten und der Endknoten durch einen einzigen Eingangsknoten ersetzt, und jeder Knoten kann von jedem anderen Knoten aus erreicht werden, ohne daß man mit dem externen Zeiger entry starten muß: … In einer doppelt-verketteten Liste enthält jeder Knoten zwei Zeiger, einen auf den Nachfolgerknoten und einen auf den Vorgängerknoten. Die Liste kann in beiden Richtungen traversiert werden: …

3.3 Verkettete Listen Beispiel: Josephus-Funktion N Personen (rechts N=9) wählen einen Anführer, indem sie sich in einem Kreis aufstellen und jede M-te Person (M=5) aus dem Kreis entlassen. Nach dem Weggang einer Person wird der Kreis wieder geschlossen. Die letzte Person wird der Anführer (ein mathematisch gebildeter Möchtegern-Anführer ermittelt im Voraus, welche Position er im Kreis einzunehmen hat). Josephus-Funktion J(N, M): Die Identität des gewählten Anführers. J(9,5) = 8.

3.3 Verkettete Listen Doppelt-verkettete Listen: entry null e1 e2 … ei Doppelt-verkettete zirkuläre Listen: e1 e2 en ei ei+1 … entry Eine lineare Liste ist manchmal handlicher zu benutzen, wenn der Schwanz auf den Kopf der Liste zurückverweist, wodurch eine zirkuläre Liste entsteht. In einer zirkulären Liste werden der Anfangsknoten und der Endknoten durch einen einzigen Eingangsknoten ersetzt, und jeder Knoten kann von jedem anderen Knoten aus erreicht werden, ohne daß man mit dem externen Zeiger entry starten muß: … In einer doppelt-verketteten Liste enthält jeder Knoten zwei Zeiger, einen auf den Nachfolgerknoten und einen auf den Vorgängerknoten. Die Liste kann in beiden Richtungen traversiert werden: …

3.3 Verkettete Listen Mehrfach verkettete Listen: Knoten haben mehrere Verbindungsfelder und gehören zu unabhängig verwalteten verketteten Listen. Bsp. a, b: Start einer Liste. Doppelt-verkettete Listen: Spezialfall von mehrfach verketteten Listen

3.3 Verkettete Listen Realisierung verketteter Listen: i.d.R. Referenzen auf Objekte Arrays von Ganzzahlen, um verkettete Listen, z.B. für Josephus-Spiel (rechts), zu implementieren. Wir realisieren Verbindungen mit Arrayindizes. (Warum und wann ist dies möglich?) Die Abstraktionsmöglichkeit von Java hilft, solche Details zu verbergen

3.4 Arrays vs. Verkettete Listen Listen: Lokale Veränderungen können mit einem Aufwand durchgeführt werden, der unabhängig von der Größe der Liste ist - vorausgesetzt wir kennen die Speicherpositionen der involvierten Elemente Verkettete Listen: Ein aus einer Liste gelöschtes Element hinterlässt keine Lücke, die wie beim Array gefüllt werden müsste. Stattdessen hinterlässt es freien Speicherplatz  Speicherplatzverwalter (garbage collector) sammelt den nicht mehr benötigten Speicherplatz wieder ein. Das Spektrum der Datenstrukturen reicht von statischen Objekten, wie einer Tabelle von Konstanten, zu dynamischen Strukturen wie Listen. Listen erlauben nicht nur, die gespeicherten Datenwerte zu ändern, sondern auch die Größe und Struktur der Liste können sich zur Laufzeit auf Grund von Einfüge- und Löschoperationen oder Reorganisationen verändern. Die meisten der bisher diskutierten Datenstrukturen können ihre Größe und Struktur nur eingeschränkt verändern. Ein zirkulärer Puffer z.B. unterstützt Einfügen an einem und Löschen am anderen Ende und kann bis zu einer vorgegebenen maximalen Größe wachsen. Ein Heap unterstützt Löschen an einem Ende des Arrays, und Einfügen irgendwo im Array. In einer Liste kann jede lokale Veränderung mit einem Aufwand durchgeführt werden, der unabhängig von der Größe der Liste ist - vorausgesetzt wir kennen die Speicherpositionen der involvierten Elemente. Die Schlüsselidee, um diese Forderung zu erfüllen, besteht darin, benötigten Speicherplatz nicht mehr wie beim Array in einem großen zusammenhängenden Teil zu allozieren, sondern den benötigten Speicherplatz dynamisch in kleinen Fragmenten anzulegen, die ein gegebenes Objekt speichern können. Da dann die Datenelemente mehr oder weniger zufallsmäßig verstreut und nicht zusammenhängend im Speicher abgelegt werden, erzeugt eine Einfüge- oder Löschoperation keinen Dominoeffekt, durch den andere Datenelemente herumgeschoben werden. Ein Element wird irgendwo im Speicher abgelegt und mit anderen Elementen durch sogenannte Zeiger oder Referenzen (d.h. Speicheradressen, an denen die Elemente gegenwärtig abgelegt sind) verknüpft.

3.4 Arrays vs. Verkettete Listen Primzahlensieb von Eratosthenes: Array vorteilhaft, weil die Effizienz des Algorithmus darauf beruft, schnell auf eine beliebige Arrayposition zugreifen zu können Josephus-Problem: Verkettete Liste vorteilhaft, weil die Effizienz des Algorithmus darauf beruft, schnell Elemente entfernen zu können. Achtung: Verkettete Listen könnten durchaus intern mit Arrays realisiert werden! Die Wechselwirkung zwischen Datenstrukturen und Algorithmen bildet das Herz des Entwurfsprozesses und Kern der Vorlesung! Das Spektrum der Datenstrukturen reicht von statischen Objekten, wie einer Tabelle von Konstanten, zu dynamischen Strukturen wie Listen. Listen erlauben nicht nur, die gespeicherten Datenwerte zu ändern, sondern auch die Größe und Struktur der Liste können sich zur Laufzeit auf Grund von Einfüge- und Löschoperationen oder Reorganisationen verändern. Die meisten der bisher diskutierten Datenstrukturen können ihre Größe und Struktur nur eingeschränkt verändern. Ein zirkulärer Puffer z.B. unterstützt Einfügen an einem und Löschen am anderen Ende und kann bis zu einer vorgegebenen maximalen Größe wachsen. Ein Heap unterstützt Löschen an einem Ende des Arrays, und Einfügen irgendwo im Array. In einer Liste kann jede lokale Veränderung mit einem Aufwand durchgeführt werden, der unabhängig von der Größe der Liste ist - vorausgesetzt wir kennen die Speicherpositionen der involvierten Elemente. Die Schlüsselidee, um diese Forderung zu erfüllen, besteht darin, benötigten Speicherplatz nicht mehr wie beim Array in einem großen zusammenhängenden Teil zu allozieren, sondern den benötigten Speicherplatz dynamisch in kleinen Fragmenten anzulegen, die ein gegebenes Objekt speichern können. Da dann die Datenelemente mehr oder weniger zufallsmäßig verstreut und nicht zusammenhängend im Speicher abgelegt werden, erzeugt eine Einfüge- oder Löschoperation keinen Dominoeffekt, durch den andere Datenelemente herumgeschoben werden. Ein Element wird irgendwo im Speicher abgelegt und mit anderen Elementen durch sogenannte Zeiger oder Referenzen (d.h. Speicheradressen, an denen die Elemente gegenwärtig abgelegt sind) verknüpft.

3.5 Zusammengesetzte Datenstrukturen Arrays und verkettete Listen liefern eine erste Stufe der Abstraktion, auf der komplexere Datenstrukturen definiert werden können Mehrdimensionale Arrays: Deklaration: Typ[][] Arrayname // 2-dimensional Typ[][][] Arrayname // 3-dimensional alternativ: Typ Arrayname[][] Initialisierung: Arrayname = new Typ[Size1][Size2]; oder (für nicht notwendigerweise rechteckige Arrays): Arrayname = new Typ[Size][]; for (int i = 0; i < Size; i++) Arrayname[i] = new Typ[Size_i];

3.5 Zusammengesetzte Datenstrukturen Beispiel: Deklaration: int[][] table; Erzeugung: table = new int[3][2]; oder table = new int[3][]; table[1] = new int[2];

3.5 Zusammengesetzte Datenstrukturen Beispiel: Effiziente Speicherung von nicht-rechteckigen Strukturen int pascal [][] = { { 1 }, { 1, 1 }, { 1, 2, 1 }, { 1, 3, 3, 1 }, { 1, 4, 6, 4, 1 } } ; 1 1 1 2 1 3 1 4 6 Pascal[4][1]

3.5 Zusammengesetzte Datenstrukturen Beispiel: Darstellung von Graphen mit Adjazenzmatrix Einfachheitshalber ordnen wir den Knoten Indizes zu. Adjazenzmatrix = 2D Matrix: Zeile i und Spalte j hat den Wert true, wenn es eine Kante von Knoten i zu Knoten j gibt. Das Array ist für ungerichtete Graphen symmetrisch. Per Konvention weisen wir den Elementen in der Diagonalen true-Werte zu. Boolean adj[][] = new boolean[V][V];

3.5 Zusammengesetzte Datenstrukturen Dünn besetzte Adjazenzmatrix: Ein Graph mit wenigen Kanten kann auch mit einem Array von Adjazenzlisten darstellt werden. Der Speicherbedarf ist proportional zur Anzahl der Knoten plus Anzahl der Kanten.

Zusammenfassung 3.1 Grundlegendes 3.2 Arrays (Felder) 3.3 Verkettete Listen 3.4 Arrays vs. Verkettete Listen 3.5 Zusammengesetzte Datenstrukturen