ALP II Dynamische Datenmengen Datenabstraktion (Teil 2)

Ähnliche Dokumente
Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Bäume. Text. Prof. Dr. Margarita Esponda SS 2012 O4 O5 O6 O ALP2-Vorlesung, M. Esponda

Informatik 11 Kapitel 2 - Rekursive Datenstrukturen

Der linke Teilbaum von v enthält nur Schlüssel < key(v) und der rechte Teilbaum enthält nur Schlüssel > key(v)

Vorlesung Datenstrukturen

Hochschule Augsburg, Fakultät für Informatik Name:... Prüfung "Programmieren 1", IN1bac, WS 10/11 Seite 1 von 6

Algorithmen und Datenstrukturen (für ET/IT)

Objektorientierte Programmierung

Große Übung Praktische Informatik 1

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny

Algorithmen und Datenstrukturen

6 Speicherorganisation

Einführung Elementare Datenstrukturen. Der Konstruktor muß den Listenkopf head erzeugen. Der Vorgänger und Nachfolger von head ist head selbst.

Kapitel 3: Datentyp Liste

(06 - Anwendungen von Stapeln und Schlangen)

Advanced Programming in C

Abstrakte Datentypen.

Einführung in die Programmierung

- k Maximalwerte aus Menge mit n >> k Elementen (Rangfolgebestimmung von Suchmaschinen!) Die typische Operationen:

Studentische Lösung zum Übungsblatt Nr. 7

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12. Kapitel 13. Bäume. Bäume

5.5.8 Öffentliche und private Eigenschaften

Theoretische Informatik 1 WS 2007/2008. Prof. Dr. Rainer Lütticke

Datenstrukturen & Algorithmen

Klausur zur Veranstaltung Programmierung (fortgeschrittene Konzepte)

Suchbäume. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

1 Polymorphie (Vielgestaltigkeit)

Struktur am Beispiel einer Liste

Geordnete Binärbäume

Verkettete Listen. Implementierung von einfach verketteten Listen. Implementierung von doppelt verketteten Listen

Folge 18 - Vererbung

Institut für Informatik

1. Typen und Literale (6 Punkte) 2. Zuweisungen (6 = Punkte)

Lösungsvorschläge. zu den Aufgaben im Kapitel 4

Inhaltsverzeichnis. Praktikum Algoritmen und Datenstrukturen WS2004/2005 Paul Litzbarski Stefan Nottorf. Druckmanager allgemein 2.

Zusammenfassung: Programmieren 2 (C#)

Objektorientierte Programmierung. Kapitel 12: Interfaces

Informatik II, SS 2014

Objektorientierte Programmierung

Repetitorium Informatik (Java)

Theorie zu Übung 8 Implementierung in Java

5.4 Klassen und Objekte

8 Baum in perfekter Komposition

Algorithmen & Datenstrukturen Lösungen zu Blatt 9 HS 16

Fortgeschrittene Programmiertechnik Klausur WS 2014/15 Angewandte Informatik Bachelor

Probeklausur: Programmierung WS04/05

Java. Wir verwenden oft Java für Datenstrukturen und Algorithmen. Die Vorlesung ist aber von der Programmiersprache unabhängig.

Exceptions. Prof. Dr. Margarita Esponda SS M. Esponda-Argüero

Javakurs FSS Lehrstuhl Stuckenschmidt. Tag 3 - Objektorientierung

368 4 Algorithmen und Datenstrukturen

PIWIN 1 Übung Blatt 5

Programmieren in Java

Vorlesung Programmieren

Probeklausur: Programmierung WS04/05

2.2 Prozesse in Java

Einstieg in die Informatik mit Java

Einführung in die Programmierung für Wirtschaftsinformatik

Objektorientierte Programmierung

Klassendefinitionen verstehen

Programmieren in Haskell. Abstrakte Datentypen

Inhalte Informatik. I1 Grundprinzip des objektorientierten Modellierens I3 Modellieren von Netzwerkanwendungen

Vorkurs C++ Programmierung

AuD-Tafelübung T-B5b

Name: Seite 2. Beantworten Sie die Fragen in den Aufgaben 1 und 2 mit einer kurzen, prägnanten Antwort.

Ein Algorithmus heißt rekursiv, wenn er sich selbst aufruft. Meist werden nur einzelne Module eines Gesamtalgorithmus rekursiv verwendet.

HEUTE. Datenstrukturen im Computer. Datenstrukturen. Rekursion. Feedback Evaluation. abstrakte Datenstrukturen

3 Objektorientierte Konzepte in Java

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

EINI WiMa/LW. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

Grundzüge der Programmierung. Wiederverwendung VERERBUNG

7. Schnittstellen Grundlagen zu Schnittstellen. 7. Schnittstellen

Einstieg in die Informatik mit Java

Kapitel 2: Analyse der Laufzeit von Algorithmen Gliederung

C# im Vergleich zu Java

Verkettete Liste. = null. kopf

Java Einführung Klassendefinitionen

Übungspaket 31 Entwicklung eines einfachen Kellerspeiches (Stacks)

Grundkonzepte java.util.list

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI

einkonto.zahle(+100); //Transaktion Einzahlung einkonto.zahle(-20); //Transaktion Auszahlung einkonto.zahle(+30); //Transaktion Einzahlung

Programmierkurs Java

Algorithmen und Datenstrukturen

Bäume. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 10: Collections 4. Inhalt. Bäume. Einführung. Bäume.

3 Objektorientierte Konzepte in Java

Zur Erinnerung: Threads. Threadverwaltung. Threads: Prioritäten. Beispiel Flugbuchungsprogramm. Nichtdeterminismus

Fortgeschrittene Programmiertechnik Klausur SS 2015 Angewandte Informatik Bachelor

Kapitel 6. Vererbung

Vorlesung Informatik 2 Algorithmen und Datenstrukturen. (20 Graphen) T. Lauer

Vorbereitungen Download. AVO-Übung 6. Beispiel. Slice. Varianten u.a. für Linux, Windows, OS X ICE-Dokumentation ICE-Binaries (inkl.

Java-Implementierung der Priority-Queue und des Huffman-Algorithmus Effiziente Algorithmen SS12 Übung 4 Aufgabe 5 Johannes Hein

Javakurs zu Informatik I. Henning Heitkötter

Einführung in die Programmierung Vorlesungsprüfung

Kapitel 6. Vererbung

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12. Kapitel 8. Arrays. Arrays

Programmieren I. Kapitel 8. Vererbung

Welche Informatik-Kenntnisse bringen Sie mit?

B Java RMI B.2 B.4. 1 Java. 1.2 Methoden. 1.1 Objekte (2) 1.1 Objekte. Objektorientierte Sprache. Klassenbeschreibung. Methode ist eine Art Funktion

Grundlagen der Programmierung Prof. H. Mössenböck. 11. Objektorientierung

Suchen und Sortieren

Programmierung mit C Zeiger

Transkript:

ALP II Dynamische Datenmengen Datenabstraktion (Teil 2) O1 O2 O3 O4 SS 2012 Prof. Dr. Margarita Esponda 49

Einfach verkettete Listen O1 O2 O3 50

Einführung Einfach verkettete Listen sind die einfachsten dynamischen Datenstrukturen, die zur Laufzeit an den tatsächlichen Speicherbedarf anpassen können. Eine Liste besteht aus einer Menge von Knoten, die untereinander verkettet sind. Jeder Knoten besteht aus einer Referenz auf das eigentliche zu speichernde Objekt und eine Referenz auf das nächste Element der Liste. Das letzte Element der Liste zeigt auf die Konstante null O1 O2 O3 51

Implementierung O1 O2 O3 null Wir haben eine rekursive Klassendefinition, class ListNode <T> { T element; ListNode <T> next;... weil das next-element zu der gleichen Objekt- Klasse gehört, die wir gerade definieren. 52

Implementierung O1 O2 O3 null class ListNode <T> { T element; ListNode<T> next; // Konstruktoren ListNode( T element, ListNode<T> next ){ this.element = element; this.next = next; ListNode() { this( null, null ); Zwei Konstruktoren: Einer, der nur einen leeren Knoten erzeugt und einen, der gleichzeitig ein Objekt in dem Knoten speichert und die Referenz auf den nächsten Knoten bekommt. 53

Stapel als verkettete Liste Mit Hilfe von verketteten Listen lässt sich sehr einfach ein Stapel implementieren. Wir müssen dabei nicht mehr überprüfen, ob der Stapel voll ist. Wir brauchen ein -Element, das eine Referenz auf ein ListNode- Objekt ist. Mit dieser Referenz können wir bei einer push-operation neue Elemente am Anfang der Liste verketten oder entfernen, wenn eine pop- Operation stattfindet. O1 O2 O3 null 54

Stapel-Schnittstelle In dieser Implementierung werden wir eine EmptyStackException erzeugen bei dem Versuch, ein Element zu entfernen oder zu lesen (pop- und top- Operationen), wenn die Liste leer ist. public interface Stack <T>{ public void push( T element ); public T pop() throws EmptyStackException; public T top() throws EmptyStackException; public boolean empty(); 55

Einfache Implementierung der Stapel-Schnittstelle Ein Konstruktor wird definiert, der mit der Konstante null initialisiert. public class ListStapel<T> implements Stack <T> {... /* Instanzvariablen */ private ListNode<T> ; /* Konstruktor */ public ListStapel() { = null; /* Methoden */ 56

Implementierung der empty-operation null Der Stapel ist leer, wenn das -Element auf die Konstante null zeigt public boolean empty () { return == null; 57

Implementierung der push-operation O1 O2 O3 Das T-Objekt e soll am Anfang der Liste eingefügt werden public void push ( T element ) { ListNode<T> temp = new ListNode<T> (); temp.element = element; temp.next = ; = temp; 58

Implementierung der push-operation O1 O2 O3 temp public void push ( T element ) { ListNode<T> temp = new ListNode<T> (); temp.element = element; temp.next = ; = temp; 59

Implementierung der push-operation e O1 O2 O3 temp public void push ( T element ) { ListNode<T> temp = new ListNode<T> (); temp.element = element; temp.next = ; = temp; 60

Implementierung der push-operation e O1 O2 O3 temp public void push ( T element ) { ListNode<T> temp = new ListNode<T> (); temp.element = element; temp.next = ; = temp; 61

Implementierung der push-operation e O1 O2 O3 temp public void push ( T element ) { ListNode<T> temp = new ListNode<T> (); temp.element = element; temp.next = ; = temp; 62

Implementierung der push-operation e O1 O2 O3 Mit Hilfe eines ListNode-Konstruktors, der als erster Parameter das zu speichernde Objekt element bekommt, und als zweiter Parameter eine Referenz auf ein ListNode-Objekt bekommt, können wir sehr einfach unsere push-operation wie folgt implementieren. public void push ( T element ) { = new ListNode<T> ( element, ); 63

Implementierung der pop-operation null Wenn innerhalb einer pop-operation festgestellt wird, dass der Stapel leer ist, wird ein EmptyStackException- Objekt geworfen und die pop-operation unterbrochen. public T pop() throws EmptyStackException { if ( empty() ) throw new EmptyStackException(); T element =.element; =.next; return element; 64

Implementierung der pop-operation Wenn der Stapel nicht leer ist element e O1 O2 O3 public T pop() throws EmptyStackException { if ( empty() ) throw new EmptyStackException(); T element =.element; =.next; return element; 65

Implementierung der pop-operation Wenn der Stapel nicht leer ist element e e O1 O2 O3 public T pop() throws EmptyStackException { Die Objekt-Referenz, die sich in dem ersten Knoten befindet, wird in die lokale Variable element gespeichert. if ( empty() ) throw new EmptyStackException(); T element =.element; =.next; return element; 66

Implementierung der pop-operation element e e O1 O2 O3 public T pop() throws EmptyStackException { if ( empty() ) throw new EmptyStackException(); T element =.element; =.next; return element; 67

Implementierung der pop-operation element garbage O1 O2 O3 e return public T pop() throws EmptyStackException { if ( empty() ) throw new EmptyStackException(); T element =.element; =.next; return element; 68

Implementierung der pop-operation garbage O1 O2 O3 Das entfernte ListNode-Objekt bleibt ohne eine einzige Referenz, das auf es zeigt, und verwandelt sich in Datenspeichermüll, der später von dem Java- garbage collector beseitigt wird. 69

Einfache Implementierung einer Warteschlange dequeue FIFO - Datenstruktur tail O1 O2 O3 enqueue "First In - First Out" Wenn wir eine Warteschlange mit Hilfe einer verketteten Liste implementieren, brauchen wir nicht mehr zu überprüfen, ob die Warteschlange voll ist. Operationen der Warteschlange enqueue dequeue empty 70

Warteschlange-Schnittstelle In dieser Implementierung werden wir eine EmptyQueueException erzeugen bei dem Versuch, ein Element zu entfernen oder zu lesen (dequeue-operation und -Operationen), wenn die Liste leer ist. public interface Queue<T> { public void enqueue( T newelement ) ; public T dequeue() throws EmptyQueueException; public T () throws EmptyQueueException; public boolean empty(); 71

Warteschlange-Implementierung public class ListQueue<T> implements Queue<T> { ListNode<T> ; ListNode<T> tail; public ListQueue() { this. = null; this.tail = null;... 72

Implementierung der empty-operation tail null Die Warteschlange ist leer, wenn das -Element auf die Konstante null zeigt public boolean empty () { return == null; 73

enqueue-operation tail null Wenn die Liste leer ist public void enqueue ( T newelement ) { if ( empty() ) = tail = new ListNode<T> ( newelement ); else tail = tail.next = new ListNode<T>( newelement ); 74

O1 tail enqueue-operation Das zu speichernde Element muss zuerst in ein ListNode-Objekt verpackt werden, und und tail bekommen eine Referenz aus den neuen Knoten zugewiesen. public void enqueue ( T newelement ) { if ( empty() ) = tail = new ListNode<T> ( newelement ); else tail = tail.next = new ListNode<T>( newelement ); 75

enqueue-operation tail O0 O1 O2 O3 Wenn die Liste nicht leer ist public void enqueue ( T newelement ) { if ( empty() ) = tail = new ListNode<T> ( newelement ); else tail = tail.next = new ListNode<T>( newelement ); 76

enqueue-operation tail O0 O1 O2 O3 newe Zuerst wird das zu speichernde neue Objekt in einen neu erzeugten Listenknoten (ListNode) verpackt. public void enqueue ( T newelement ) { if ( empty() ) = tail = new ListNode<T> ( newelement ); else tail = tail.next = new ListNode<T>( newelement ); 77

enqueue-operation tail O0 O1 O2 O3 newe Die Referenz, die von dem ListNode- Konstruktor erzeugt wird, bekommt tail.next zugewiesen. public void enqueue ( T newelement ) { if ( empty() ) = tail = new ListNode<T> ( newelement ); else tail = tail.next = new ListNode<T>( newelement ); 78

enqueue-operation tail O0 O1 O2 O3 newe Zum Schluss bekommt tail auch die gleiche Referenz wie tail.next. public void enqueue ( T newelement ) { if ( empty() ) = tail = new ListNode<T> ( newelement ); else tail = tail.next = new ListNode<T>( newelement ); 79

dequeue-operationen tail e O1 O2 O3 Wenn die Liste nicht leer ist public T dequeue() throws EmptyQueueException { if (empty () ) throw new EmptyQueueException(); T element =.element; =.next; return element; 80

dequeue-operationen tail element e e O1 O2 O3 Die Referenz des Elements, das am Anfang der Warteschlange gespeichert ist, wird der Variablen element zugewiesen. public T dequeue() throws EmptyQueueException { if (empty () ) throw new EmptyQueueException(); T element =.element; =.next; return element; 81

dequeue-operationen tail element e e O1 O2 O3 public T dequeue() throws EmptyQueueException { if (empty () ) throw new EmptyQueueException(); T element =.element; =.next; return element; 82

dequeue-operationen tail element e return e O1 O2 O3 public T dequeue() throws EmptyQueueException { if (empty () ) Die Referenz des entfernten Objekts wird als Ergebnis zurückgegeben. throw new EmptyQueueException(); T element =.element; =.next; return element; 83

dequeue-operationen tail e O1 O2 O3 Weil keine Referenz auf das entfernte ListNode-Objekt zeigt, bleibt es Speicherdatenmüll, bis es vom Java- garbage collector gelöscht wird. 84

Allgemeine dynamische Datenmenge Wenn wir allgemeine dynamische Datenmengen mit Hilfe von Listen implementieren möchten, müssen wir an einer beliebigen Stelle der Liste Elemente einfügen und löschen können. Dafür brauchen wir ein weiteres Referenz-Objekt (current), das sich durch die Liste bewegt. Wir werden eine Einfüge-Operation definieren, die ein Element nach dem current - Zeiger einfügt und eine Lösch-Operation, die ein Element nach dem current-zeiger löscht. insert delete current O1 O2 O4 O3 85

Einfügen an einer beliebigen Stelle der Liste current........ O1 O4 O3 temp... ListNode<T> temp = new ListNode<T>(); temp.element = newe; temp.next = current.next; current.next = temp;... 86

Einfügen an eine beliebige Stelle der Liste current........ O1 O4 O3 temp newe... ListNode<T> temp = new ListNode<T>(); temp.element = newe; temp.next = current.next; current.next = temp;... 87

Einfügen an eine beliebige Stelle der Liste current........ O1 O4 O3 temp newe... ListNode<T> temp = new ListNode<T>(); temp.element = newe; temp.next = current.next; current.next = temp;... 88

Einfügen an eine beliebige Stelle der Liste current........ O1 O4 O3 temp newe... ListNode<T> temp = new ListNode<T>(); temp.element = newe; temp.next = current.next; current.next = temp;... 89

Einfügen an eine beliebige Stelle der Liste current........ O1 O4 O3 temp newe current.next = new ListNode<T>( newe, current.next ); 90

Löschen an einer beliebigen Stelle der Liste current next next next........ O1 O4 O3 current.next = current.next.next; 91

Löschen an einer beliebigen Stelle der Liste current garbage next next next........ O1 O4 O3 current.next = current.next.next; Das entfernte ListNode-Objekt bleibt ohne eine einzige Referenz, die auf es zeigt, und verwandelt sich in Datenspeichermüll, der später von dem Java- garbage collector beseitigt wird. 92

"Header"-Knoten ("Dummy"-Knoten) Die Einfüge- und Löschoperationen, wie wir bis jetzt diskutiert haben, gehen davon aus, dass immer ein Vorgänger-Element vorhanden ist. Das macht unsere Implementierung einfacher, weil die speziellen Fälle - Löschen des ersten Elements der Liste- - Einfügen, wenn die Liste leer istnicht berücksichtigt werden müssen. Um unsere Implementierung übersichtlich und einfach zu halten, benutzen wir einen Dummy-Knoten (sentinel), der selbst keine Elemente speichert und nur benutzt wird, um diese speziellen Fälle zu vermeiden, weil auf diese Weise jeder Knoten der Liste immer einen Vorgänger haben wird. 93

"Dummy"-Knoten current Dummy O2 O4 O3 Unsere Liste ist jetzt leer, wenn sich nur der "Dummy"-Knoten in ihr befindet. public boolean empty () { Dummy return.next == null; 94

Einschränkungen bei einfach verketteten Listen Probleme: Der current-zeiger kann nur nach vorne bewegt werden. Um den Vorgänger desjenigen Knotens zu finden, auf den current zeigt, müssen wir die ganze Liste von an durchlaufen. Das ist im allgemeinen sehr ineffizient. current current current Dummy O2 O4 O3 95

Doppelt verkettete Listen tail Dummy O1 O2 Dummy class ListNode <T> { T element; ListNode <T> next; ListNode <T> prev;... Bei doppelt verketteten Listen kann sich current problemlos in beide Richtungen bewegen. Die Einfüge- und Lösch- Operation ändert sich, weil wir jetzt immer eine doppelte Verkettung erstellen müssen. 96

Doppelt verkettete leere Liste Dummy Dummy tail Bei doppelt verketteten Listen ist es sinnvoll, einen Zeiger auf das letzte Element zu haben. public boolean empty { return.next == tail; 97

Einfügen current prev O0 next prev next prev O1 O3 next...... ListNode<T> temp = new ListNode<T>( x ); temp.prev = current; temp.next = current.next; temp.prev.next = temp; temp.next.prev = temp; current = temp; 98

Einfügen current prev O0 next prev next prev O1 O3 next temp prev x next...... ListNode<T> temp = new ListNode<T>( x ); temp.prev = current; temp.next = current.next; temp.prev.next = temp; temp.next.prev = temp; current = temp; 99

Einfügen current prev O0 next prev next prev O1 O3 next temp prev x next...... ListNode<T> temp = new ListNode<T>( x ); temp.prev = current; temp.next = current.next; temp.prev.next = temp; temp.next.prev = temp; current = temp; 100

Einfügen current prev O0 next prev next prev O1 O3 next temp prev x next...... ListNode<T> temp = new ListNode<T>( x ); temp.prev = current; temp.next = current.next; temp.prev.next = temp; temp.next.prev = temp; current = temp; 101

Einfügen current prev O0 next prev next prev O1 O3 next temp prev x next...... ListNode<T> temp = new ListNode<T>( x ); temp.prev = current; temp.next = current.next; temp.prev.next = temp; temp.next.prev = temp; current = temp; 102

Einfügen current prev O0 next prev next prev O1 O3 next temp prev x next...... ListNode<T> temp = new ListNode<T>( x ); temp.prev = current; temp.next = current.next; temp.prev.next = temp; temp.next.prev = temp; current = temp; 103

Einfügen current prev O0 next prev next prev O1 O3 next temp prev x next...... ListNode<T> temp = new ListNode<T>( x ); temp.prev = current; temp.next = current.next; temp.prev.next = temp; temp.next.prev = temp; current = temp; 104

Löschen current prev next prev next prev x O1 O3 next Mit doppelt verketteten Listen können wir genau das Objekt löschen, auf das current zeigt.... current.prev.next = current.next;... current.next.prev = current.prev; current = ; 105

Löschen current prev next prev next prev x O1 O3 next... current.prev.next = current.next;... current.next.prev = current.prev; current = ; 106

Löschen current prev next prev next prev x O1 O3 next... current.prev.next = current.next;... current.next.prev = current.prev; current = ; 107

Löschen prev next prev next prev x O1 O3 next... current.prev.next = current.next;... current.next.prev = current.prev; current = ; 108

Löschen garbage prev next prev next prev x O1 O3 next... current.prev.next = current.next;... current.next.prev = current.prev; current = ; 109

Löschen garbage prev next prev next prev x O1 O3 next... current.prev.next = current.next;... current.next.prev = current.prev; current = ; 110