Algorithmen und Datenstrukturen 3. Vorlesung

Ähnliche Dokumente
SS10 Algorithmen und Datenstrukturen 2. Kapitel Fundamentale Datentypen und Datenstrukturen

Algorithmen und Datenstrukturen 3. Vorlesung

12. Dynamische Datenstrukturen

16. Dynamische Datenstrukturen

Grundlegende Datentypen

Wiederholung: Zusammenfassung Felder. Algorithmen und Datenstrukturen (für ET/IT) Definition Abstrakter Datentyp. Programm heute

Übung Algorithmen und Datenstrukturen

Counting - Sort [ [ ] [ [ ] 1. SS 2008 Datenstrukturen und Algorithmen Sortieren in linearer Zeit

8 Elementare Datenstrukturen

Abstrakter Datentyp (ADT): Besteht aus einer Menge von Objekten, sowie Operationen, die auf diesen Objekten wirken.

Organisatorisches. Algorithmen und Datenstrukturen (für ET/IT) Programm heute. Definition Feld. Definition Feld

11. Elementare Datenstrukturen

ALP II Dynamische Datenmengen Datenabstraktion

Algorithmen und Datenstrukturen (für ET/IT)

13. Dynamische Datenstrukturen

Informatik II, SS 2014

Programm heute. Algorithmen und Datenstrukturen (für ET/IT) Feld als sequentielle Liste. Definition Feld

Algorithmen und Datenstrukturen (für ET/IT)

1 Abstrakte Datentypen

Algorithmen und Datenstrukturen (für ET/IT)

Einführung in die Objektorientierte Programmierung Vorlesung 18: Lineare Datenstrukturen. Sebastian Küpper

Programm heute. Algorithmen und Datenstrukturen (für ET/IT) Definition Feld. Feld als sequentielle Liste

Abstrakte Datentypen und Datenstrukturen

ALP II Dynamische Datenmengen Datenabstraktion (Teil 2)

Informatik II, SS 2016

Übung Algorithmen und Datenstrukturen

Algorithmen I. Tutorium 1-3. Sitzung. Dennis Felsing

7. Verkettete Strukturen: Listen

Schwerpunkte. Verkettete Listen. Verkettete Listen: 7. Verkettete Strukturen: Listen. Überblick und Grundprinzip. Vergleich: Arrays verkettete Listen

Nachtrag: Vergleich der Implementierungen von Stack

Datentypen. strukturierte. elementare. skalare reelle statische dynamische int. list. real float. set. record. inhomogen. homogen

Fallstudie: Online-Statistik

ContainerDatenstrukturen. Große Übung 4

Informatik II, SS 2014

Einführung in die Programmiertechnik

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

5.3 Doppelt verkettete Listen

Datenstrukturen sind neben Algorithmen weitere wichtige Bausteine in der Informatik

Abstrakte Datentypen und Datenstrukturen

Abstrakte Datentypen und deren Implementierung in Python

Spezielle Datenstrukturen

1. Die rekursive Datenstruktur Liste

12.3 Ein Datenmodell für Listen

Einfügen immer nur am Kopf der Liste Löschen auch nur an einem Ende (2 Möglichkeiten!)

Praktikum zu DAP 2. Abstrakte Datentypen und Datenstrukturen. Überblick. Motivation. Freiwilliger Linux-Kurs von Wilfried Rupflin und Sven Jörges

Vollständigkeit. Klassifikation von Operationen

Übung Algorithmen und Datenstrukturen

Datenstrukturen und Algorithmen. Vorlesung 8

Stack. Queue. pop() liefert zuletzt auf den Stack gelegtes Element und löscht es push( X ) legt ein Element X auf den Stack

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

3. Übungsblatt zu Algorithmen I im SoSe 2017

Vorlesung Informatik 2 Algorithmen und Datenstrukturen

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen, Bäume)

6. Verkettete Strukturen: Listen

Kapitel 4: Dynamische Datenstrukturen. Algorithmen und Datenstrukturen WS 2017/18. Pro f. Dr. Sán do r Fe k e te

Algorithmen und Datenstrukturen SS09. Foliensatz 7. Michael Brinkmeier. Technische Universität Ilmenau Institut für Theoretische Informatik

Gliederung. 5. Compiler. 6. Sortieren und Suchen. 7. Graphen

Algorithmen I. Tutorium 1-4. Sitzung. Dennis Felsing

Kap. 2: Abstrakte Datentypen Kap. 3: Sortieren

Vorlesung Datenstrukturen

Abschnitt 10: Datenstrukturen

Elementare Datenstrukturen

Einführung in die Informatik

Stapel (Stack, Keller)

Datenstrukturen. Mariano Zelke. Sommersemester 2012

NAME, VORNAME: Studiennummer: Matrikel:

Algorithmen und Datenstrukturen (für ET/IT) Wiederholung: Ziele der Vorlesung. Wintersemester 2012/13. Dr. Tobias Lasser

Übungsblatt 6: Softwareentwicklung I (WS 2006/07)

Advanced Programming in C

Problem: Was ist, wenn der Stapel voll ist? Idee: Erzeuge dynamisch ein grösseres Array und kopiere um. Dynamische Anpassung der Größe

Algorithmen und Datenstrukturen (für ET/IT)

Stacks, Queues & Bags. Datenstrukturen. Pushdown/Popup Stack. Ferd van Odenhoven. 19. September 2012

Grundlagen der Informatik

Beispiellösung zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 5

Ordnung im Materiallager: Datenstrukturen II. Suchen und Sortieren im Array Verkettete Listen Rekursion

Programmieren I. Kapitel 13. Listen

Algorithmen und Datenstrukturen 11. Vorlesung

Schnittstellen, Stack und Queue

Algorithmen und Datenstrukturen Kapitel 4 Neue Datenstrukturen, besseres (?) Sortieren

Grundlagen: Algorithmen und Datenstrukturen

Informatik II, SS 2018

LISTEN ALS ABSTRAKTE DATENTYPEN

Aufgaben NF 11; Seite 1

Kapitel 4. Kontrollstrukturen

Algorithmen und Datenstrukturen 1

Datenkapselung: public / private

Kapitel ADS:IV. IV. Datenstrukturen

11 Abstrakte Datentypen

Informatik II Prüfungsvorbereitungskurs

1.1 Abstrakte Datentypen 1.2 Lineare Strukturen 1.3 Bäume 1.4 Prioritätsschlangen 1.5 Graphen

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

Verbund/Struktur (record/struct)

Informatik. Pointer (Dynamisch) Vorlesung. 17. Dezember 2018 SoSe 2018 FB Ing - SB Umwelttechnik und Dienstleistung - Informatik Thomas Hoch 1

Algorithmen I - Tutorium 28 Nr. 3

Algorithmen und Datenstrukturen

Vorlesung Datenstrukturen

Algorithmen und Datenstrukturen

Transkript:

Algorithmen und Datenstrukturen 3. Vorlesung Martin Dietzfelbinger 1. April 008 FG KTuEA, TU Ilmenau AuD 1.0.008

Einfache Datentypen und Datenstrukturen Stacks (Keller, Stapel, LIFO-Speicher) Queues (Warteschlangen, FIFO-Speicher) Mengen Wörterbücher Folgen FG KTuEA, TU Ilmenau AuD 1.0.008 1

Stack (Stapel, Keller, LIFO-Speicher ) Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 pop 7 Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 1 push(1) pop 7 Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 1 top 1 push(1) pop 1 7 Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 isempty? 1 top 1 1 push(1) 7 pop false 1 Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 isempty? 1 top 1 1 push(1) 7 pop false 1 pop 1 Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 isempty? 1 top 1 1 push(1) 7 pop false 1 pop pop 1 Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 isempty? 1 top 1 1 push(1) 7 pop false 1 pop pop pop 1 Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Stack (Stapel, Keller, LIFO-Speicher ) empty push() push() push(7) 7 isempty? 1 top 1 1 push(1) 7 pop false 1 pop pop pop isempty? 1 true Last-In-First-Out FG KTuEA, TU Ilmenau AuD 1.0.008

Was sollen die Operationen bewirken? Informal: Als Stackeinträge zugelassen sind Elemente einer Menge D (Parameter). empty(()): erzeuge leeren Stack (Konstruktor). push(s, x): lege neues Element x D auf den Stack s. pop(s): entferne oberstes Element von Stack s und gib es aus (falls nicht vorhanden: Fehler) top(s): gib oberstes Element von Stack s aus (falls nicht vorhanden: Fehler) isempty(s): Ausgabe true falls Stack s leer, false sonst. Brauchen: Präzise Beschreibung FG KTuEA, TU Ilmenau AuD 1.0.008 3

Spezifikation des Datentyps Stack über D 1. Signatur: Sorten: Operationen: Elements Stacks Boolean empty: Stacks push: Stacks Elements Stacks pop: Stacks Stacks Elements top: Stacks Elements isempty: Stacks Boolean Namen von Objekttypen, Namen von Operationen mit Angabe der Typen von Argument(en) und Resultat(en). Rein syntaktische Vorschriften! Verhalten (noch) ungeklärt! FG KTuEA, TU Ilmenau AuD 1.0.008

Spezifikation des Datentyps Stack über D. Mathematisches Modell Sorten: Elements: (nichtleere) Menge D (Parameter) Stacks: D < = Seq(D) wo Seq(D) = {(a 1,..., a n ) n N, a 1,..., a n D} Boolean: {true, false} bzw. {1, 0} Objekttypen werden durch Mengen modelliert. Die leere Folge () stellt den leeren Stack dar. FG KTuEA, TU Ilmenau AuD 1.0.008 5

Spezifikation des Datentyps Stack über D. Mathematisches Modell (Forts.) Operationen: empty() = () push((a 1,..., a n ), x) := (x, a 1,..., a n ) pop((a 1,..., a n )) := top((a 1,..., a n )) := { ((a,..., a n ), a 1 ), falls n 1 undefiniert, falls n = 0 { a1, falls n 1 undefiniert, falls n = 0 isempty((a 1,..., a n )) := { false, falls n 1 true, falls n = 0 Operationen werden durch Funktionen modelliert. FG KTuEA, TU Ilmenau AuD 1.0.008 6

Spezifikation des Datentyps Stack über D Alternative: Axiome (siehe z.b. Saake/Sattler, AuD, Kap. 11) Signatur: wie oben. Axiome: s: Stacks, x : Elements pop(push(s, x)) = (s, x) top(push(s, x)) = x isempty(empty()) = true isempty(push(s, x)) = false Vorteil: Zugänglich für automatisches Beweisen von Eigenschaften der Datenstruktur. Nachteil: Finden eines geeigneten Axiomensystems evtl. nicht einfach. FG KTuEA, TU Ilmenau AuD 1.0.008 7

Implementierung von Stacks Grundsätzlich, in objektorientierter Sprache: als Klasse. Kapselung Information Hiding Signatur = Interface (Java) bzw. h-datei (C++) Parameter: Typ elements. Instanzen sind die Elemente der Menge D. (Mindestens) Zwei Möglichkeiten für innere Realisierung: verkettete Liste Array FG KTuEA, TU Ilmenau AuD 1.0.008 8

Listenimplementierung von Stacks (siehe z.b. Saake/Sattler, AuD, Kap. 13.) s: 1 a a a n (Das Symbol s.empty: Erzeuge leere Liste. s: steht für den Nullzeiger) s.push(x): Setze neuen Listenknoten mit Eintrag x an den Anfang der Liste. s: x a 1 a a n FG KTuEA, TU Ilmenau AuD 1.0.008 9

Listenimplementierung von Stacks s.pop: Entferne ersten Listenknoten (falls vorhanden) und gib Inhalt zurück. s: a a n a 1 s.top: Gib Inhalt des ersten Listenknotens aus (falls vorhanden) s: 1 a a a n FG KTuEA, TU Ilmenau AuD 1.0.008 10

Listenimplementierung von Stacks s.isempty: Falls Liste leer: Ausgabe true, sonst false s: a s: 1 Einzige Fehlermöglichkeit: Speicherüberlauf bei s.push(x). FG KTuEA, TU Ilmenau AuD 1.0.008 11

Korrektheit der Listenimplementierung Wir betrachten eine Folge Op 0 = empty, Op 1,..., Op N von Stackoperationen, wobei empty nur ganz am Anfang vorkommen darf. Diese Folge erzeugt im mathematischen Modell eine Folge (s 0, s 1, s,..., s N ) von Stacks (Tupeln) (man wende die Operationen in der offensichtlichen Weise an) und eine Folge (z 0, z 1, z,..., z N ) von Ausgaben. FG KTuEA, TU Ilmenau AuD 1.0.008 1

Korrektheit der Listenimplementierung Dabei liefern Op 0 = empty() und Op i = push(x) die Ausgabe. Die Operationen Op i = top und Op i = pop liefern normalerweise die erste Komponente von s i 1 als Ausgabe. Fehlerfall: Wenn j minimal ist, so dass Op j = top oder Op j = pop ist, wobei s j 1 = (), dann ist s j = = s N = und z j = = z N =. Die Operation Op i = isempty liefert true, wenn s i 1 = () gilt, und false, wenn s i 1 (). FG KTuEA, TU Ilmenau AuD 1.0.008 13

Korrektheit der Listenimplementierung Beispiel: OP i s i z i empty () push() () push() (, ) push(7) (7,, ) pop (, ) 7 push(1) (1,, ) top (1,, ) 1 isempty (1,, ) false pop (, ) 1 pop () pop () isempty () true pop push(3)... FG KTuEA, TU Ilmenau AuD 1.0.008 1

Korrektheit der Listenimplementierung Behauptung: Die Listenimplementierung erzeugt genau dieselbe Ausgabefolge wie das mathematische Modell, solange weder im mathematischen Modell ein Fehler (top oder pop auf leerem Stack) auftritt noch bei (push(x)) in der Implementierung ein Laufzeitfehler Speicherüberlauf eintritt. Beweis: Man zeigt per Induktion über i, dass nach Ausführen der Operation Op i folgende Behauptung (IB i ) gilt: Die Einträge in der Liste sind genau die Einträge in s i die Liste ist eine präzise Darstellung von s i. Daraus folgt unmittelbar, dass die Ausgabe bei der Implementierung mit der im mathematischen Modell übereinstimmt. FG KTuEA, TU Ilmenau AuD 1.0.008 15

Zeitaufwand bei Listenimplementierung Behauptung: Bei der Listenimplementierung hat jede einzelne Operation Kosten O(1). Das ist klar. Kosteneinheit für push(x) allerdings: Allokation eines Listenknotens Systemaufruf ( malloc in C) um einiges teurer als Arrayzugriff. FG KTuEA, TU Ilmenau AuD 1.0.008 16

Arrayimplementierung von Stacks (Vgl. Saake/Sattler, AuD, Kap. 13.1) Das Stackobjekt heißt s; es hat als Komponenten einen Zeiger/eine Referenz auf ein Array A und eine Integervariable p ( Pegel ). s: p: n 1 n m A: a n a a 1 * * * * steht für einen beliebigen Eintrag. s.empty: ( Option: m als Parameter ) Erzeuge Array A[1..m] of elements und Variable p: int ; p 0; FG KTuEA, TU Ilmenau AuD 1.0.008 17

Arrayimplementierung von Stacks s.push(x): if p = A.length then Fehler (z.b. OverflowException) else p p+1; A[p] x; s.pop: if p = 0 then Fehler (z.b. StackemptyException) else p p-1; return A[p+1]; s.top: if p = 0 then Fehler (z.b. StackemptyException) else return A[p]; s.isempty: if p = 0 then return true else return false ; FG KTuEA, TU Ilmenau AuD 1.0.008 18

Korrektheit der Arrayimplementierung Wie vorher: Gegeben ist eine Folge Op 0 = empty, Op 1,..., Op N von Stackoperationen, wobei empty nur ganz am Anfang vorkommen darf, die im mathematischen Modell eine Folge (s 0, s 1, s,..., s N ) von Stacks (Tupeln) und eine Folge von Ausgaben erzeugt. (z 0, z 1, z,..., z N ) FG KTuEA, TU Ilmenau AuD 1.0.008 19

Korrektheit der Arrayimplementierung Behauptung: Die Arrayimplementierung erzeugt genau dieselbe Ausgabefolge wie das mathematische Modell, solange weder im mathematischen Modell ein Fehler (top oder pop auf leerem Stack) auftritt noch die Höhe des Stacks s i die Arraygröße m überschreitet. Beweis: Man beweist durch Induktion über i = 0, 1,..., N, dass nach Ausführen der Operation Op i folgende Invariante gilt (falls keiner der genannten Fehler aufgetreten ist): p enthält die Länge n i von s i und s i = (A[n i ],..., A[1]) D. h.: Der Teil A[1..n i ] des Arrays stellt genau s i dar (in umgekehrter Reihenfolge). FG KTuEA, TU Ilmenau AuD 1.0.008 0

Korrektheit der Arrayimplementierung Beachte: Der Teil A[n i + 1..m] des Arrays kann völlig beliebige Einträge enthalten. D.h.: Ein Stack s im Sinn des mahematischen Modells kann durch verschieden beschriftete Arrays A[1..m] dargestellt werden. I.A.: i = 0. Anfänglich hat p den Inhalt n 0 = 0. (A[n i ],..., A[1]) ist die leere Folge (), also gleich s 0. I.V.: i > 0, und die Behauptung gilt für i 1. FG KTuEA, TU Ilmenau AuD 1.0.008 1

Korrektheit der Arrayimplementierung I.S.: Es gibt verschiedene Fälle. Fall 0a: s i 1 =, d. h., vorher ist im mathematischen Modell ein Fehler eingetreten. Dann ist nichts zu zeigen. Fall 0b: In Schritten 1,..., i 1 ist in der Implementierung ein Fehler aufgetreten. Dann ist ebenfalls nichts zu zeigen. Ab hier ist also s i 1 = (a 1,..., a ni 1 ), p hat den Inhalt n i 1 und s i 1 = (A[n i 1 ],..., A[1]). FG KTuEA, TU Ilmenau AuD 1.0.008

Korrektheit der Arrayimplementierung Man muss nun unterscheiden, was für eine Operation Op i ist. Fall 1: Op i = s.push(x). Dann ist s i = (x, a 1,..., a ni 1 ). Wenn n i 1 < m ist, wird von der Prozedur s.push(x) das Objekt x an die Stelle A[n i 1 + 1] gesetzt und p auf den Wert n i 1 + 1 = n i erhöht, woraus die Induktionsbehauptung folgt. Wenn n i 1 = m ist, tritt in der Implementierung ein Fehler ein, und die Behauptung ist trivialerweise erfüllt. Die anderen Fälle, entsprechend den anderen Operationen, behandelt man analog. (Übung.) FG KTuEA, TU Ilmenau AuD 1.0.008 3

Zeitaufwand der Arrayimplementierung Behauptung: Bei der Arrayimplementierung hat jede einzelne Operation Kosten O(1). Das sieht man durch Betrachtung der einzelnen Operationen. Bei der Initialisierung empty() darf das Array nur allokiert, nicht initialisiert werden. Man beobachte, dass hierdurch die Korrektheit nicht beeinträchtigt wird. FG KTuEA, TU Ilmenau AuD 1.0.008

Arrayimplementierung ohne Platzprobleme? Verdoppelungsstrategie In push(x): Bei Überlaufen des Arrays A nicht einen Laufzeitfehler (oder eine exception) generieren, Vorher: s: p: A: m 1 an a a 1 n=m Nachher: s: p: m +1 A: 1 m an a a 1 m x * * FG KTuEA, TU Ilmenau AuD 1.0.008 5

Arrayimplementierung ohne Platzprobleme? Verdoppelungsstrategie In push(x): Bei Überlaufen des Arrays A nicht einen Laufzeitfehler (oder eine exception) generieren, sondern ein neues, doppelt so großes Array AA allokieren. Einträge aus A nach AA kopieren. AA in A umbenennen/referenz umsetzen. (altes Array freigeben). Kosten: Θ(m), wo m = aktuelle Zahl der Einträge. FG KTuEA, TU Ilmenau AuD 1.0.008 6

Kostenanalyse bei Verdoppelungsstrategie: Operationenfolge Op 0 = empty, Op 1,..., Op N Arraygröße am Anfang: m 0. Jede Operation hat Kosten O(1), außer wenn die Arraygröße von m 0 i 1 auf m 0 i wächst. Hier entstehen Kosten Θ(m 0 i 1 ). FG KTuEA, TU Ilmenau AuD 1.0.008 7

k := Anzahl der push-operationen in Op 1,..., Op N Zahl der Einträge immer k, also bei Verdopplung m 0 i 1 m 0 i : m 0 i 1 < k. Sei L maximal mit m 0 L 1 < k. Gesamtkosten für die Verdopplungen also: O(m 0 i 1 ) 1 i L = O ( m 0 (1 + + + + L 1 ) ) = O ( m 0 L) = O(k). Gesamtkosten: N Θ(1) + O(k) = Θ(N). FG KTuEA, TU Ilmenau AuD 1.0.008 8

Satz Wenn ein Stack mit Arrays und der Verdoppelungsstrategie implementiert wird, betragen die Gesamtkosten für N Operationen O(N). Bemerkung: Bei der Verdoppelungsstrategie gilt weiter: Der gesamte Platzbedarf ist O(k), wenn k die maximale je erreichte Stackhöhe ist. Selbst wenn der Speicher nie bereinigt wird (kleinere, jetzt unbenutzte Arrays nicht freigegeben werden), tritt ein Speicherüberlauf erst ein, wenn die Zahl der Stackeinträge zu einem bestimmten Zeitpunkt mehr Speicher beansprucht als 1 des gesamten zur Verfügung stehenden Speichers. (Beweis: Übung.) FG KTuEA, TU Ilmenau AuD 1.0.008 9

Vergleich Listen-/Arrayimplementierung Arrayimplementierung: amortisiert (im Durch- O(1) Kosten pro Operation, schnitt über alle Operationen), Sequentieller, indexbasierter Zugriff im Speicher (cachefreundlich), Höchstens 50% des allokierten Speicherplatzes ungenutzt. Listenimplementierung: O(1) Kosten pro Operation im schlechtesten Fall (Allokierungskosten), Zusätzlicher Platz für Zeiger benötigt. FG KTuEA, TU Ilmenau AuD 1.0.008 30

Queues Warteschlangen FIFO-Listen First-In-First-Out Idee (siehe AuP-Vorlesung): vorne "head" 3 1 1 5 9 6 hinten "tail" isempty: false first: 3 enqueue(5): 3 1 1 5 9 6 5 dequeue: 1 1 5 9 6 5 3 FG KTuEA, TU Ilmenau AuD 1.0.008 31

Spezifikation des Datentyps Queue über D 1. Signatur: Sorten: Operationen: Elements Queues Boolean empty: Queues enqueue: Queues Elements Queues dequeue: Queues Queues Elements first: Queues Elements isempty: Queues Boolean Beachte: Die Signatur ist identisch zur Signatur von Stacks bis auf Umbenennungen. Rein syntaktische Vorschriften! Verhalten (noch) ungeklärt! FG KTuEA, TU Ilmenau AuD 1.0.008 3

Spezifikation des Datentyps Queue über D. Mathematisches Modell Sorten: Elements: (nichtleere) Menge D (Parameter) Queues: Seq(D) Boolean: {true, false} Die leere Folge () stellt die leere Warteschlange dar. FG KTuEA, TU Ilmenau AuD 1.0.008 33

Spezifikation des Datentyps Queue über D. Mathematisches Modell (Forts.) Operationen: empty() = () enqueue((a 1,..., a n ), x) := (a 1,..., a n, x) dequeue((a 1,..., a n )) := { ((a,..., a n ), a 1 ), falls n 1 undefiniert, falls n = 0 first((a 1,..., a n )) := { a1, falls n 1 undefiniert, falls n = 0 isempty((a 1,..., a n )) := { false, falls n 1 true, falls n = 0 FG KTuEA, TU Ilmenau AuD 1.0.008 3

Listenimplementierung von Queues Implementierung mittels einfach verketteter Listen: Übung. Skizze: vorne 3 1 1 5 9 6 hinten head: tail: 3 1 1 5 9 6 FG KTuEA, TU Ilmenau AuD 1.0.008 35

Arrayimplementierung von Queues vorne "head" 3 1 1 5 9 6 hinten "tail" * * * m m 1 0 * * * * 1 * * * 3 * * head: tail: h t t * * 6 9 5 1 1 3 * * h FG KTuEA, TU Ilmenau AuD 1.0.008 36

Arrayimplementierung von Queues Implementierung mittels Arrays, zirkulär benutzt: In Array A[0..m 1] sind durch den Inhalt h von head und den Inhalt t von tail zwei Positionen markiert. Die Idee ist, dass die Arrayeinträge A[h],A[h + 1],...,A[t 1] die Einträge (a 1,..., a n ) der Warteschlange bilden, von vorne nach hinten. Dabei werden die Indizes modulo m gerechnet; auf m 1 folgt also 0. Die Zelle A[t] ist immer leer. Um x einzufügen, wird (solange Platz ist), x an die Stelle A[tail] geschrieben und dann tail um 1 erhöht. FG KTuEA, TU Ilmenau AuD 1.0.008 37

Arrayimplementierung von Queues (Forts.) Die maximale Zahl der Einträge im Array (die Kapazität) ist m 1, da die Zelle mit Index t immer leer ist. Um in einer nichtleeren Warteschlange dequeue auszuführen, wird z = A[head] gemerkt, head wird um 1 weitergezählt (modulo m), und z wird zurückgegeben. Wenn bei einem dequeue die Warteschlange komplett geleert wird, steht in head und tail derselbe Wert. Wir benutzen die Bedingung head = tail als Test dafür, ob die Warteschlange leer ist. Um die Warteschlange (bei empty()) als leer zu initialisieren, setzen wir head und tail auf denselben Wert, z.b. 0. FG KTuEA, TU Ilmenau AuD 1.0.008 38

Arrayimplementierung von Queues (Forts.) Wenn beim Einfügen die Variable tail denselben Wert erhalten würde wie head, würde nachher A[tail] einen Queue- Eintrag enthalten. Diese Situation muss also einen Überlauf auslösen. Implementierung der Operationen auf einer Queue q: q.empty(): ( Konstruktor; Option: m als Argument ) Erzeuge Array A[0..m 1] of elements und Variable head, tail: int ; head 0; tail 0; q.isempty: if head = tail then return true else return false ; FG KTuEA, TU Ilmenau AuD 1.0.008 39

q.first: if head = tail then Fehler (z.b. QEmptyException) else return A[head] ; q.dequeue: if head = tail then Fehler (z.b. QEmptyException) else z A[head]; head (head + 1) mod m; return z q.enqueue(x): tt (tail + 1) mod m; if tt = head then Fehler (z.b. QOverflowException) else A[tail] x ; tail tt ; FG KTuEA, TU Ilmenau AuD 1.0.008 0

Alternative zu Overflow-Exception: Erzeugen eines neuen Arrays AA[0..m 1] (mit Kapazität m 1); Umkopieren der Einträge A[head], A[(head + 1) mod m],..., A[(tail 1) mod m] in AA[0], AA[1],..., AA[m ]; head 0; tail m 1; A[tail] x ; tail++ ; Umbenennen von AA in A. FG KTuEA, TU Ilmenau AuD 1.0.008 1

Satz Die angegebene Arrayimplementierung einer Queue über D ist korrekt, ohne Verdoppelungsstrategie, solange kein Fehler im Modell und kein Überlauf im Array eintritt; mit Verdoppelungsstrategie, solange kein Fehler im Modell und kein Speicherüberlauf auftritt. Beweis: Wir betrachten eine Folge Op 0 = empty, Op 1,..., Op N von Queueoperationen, wobei empty nur ganz am Anfang vorkommen darf. FG KTuEA, TU Ilmenau AuD 1.0.008

Man zeigt dann durch Induktion über i = 0,..., N, dass unter der Annahme, dass im mathematischen Modell kein Fehler auftritt, folgende Behauptung (IB) i gilt: Wenn nach Operationen Op 0, Op 1,..., Op i der Inhalt der Queue q i = (a 1,..., a ni ) ist, dann stehen nach Ausführung der Operationen in der Implementierung die Elemente a 1,..., a ni in den Positionen A[h],A[h + 1],...,A[t 1], (Indizes modulo m gerechnet), wobei h der Inhalt von head und t der Inhalt von tail ist. Insbesondere ist die Warteschlange leer genau dann wenn h = t ist. FG KTuEA, TU Ilmenau AuD 1.0.008 3

Satz Wenn eine Queue mit Arrays und der Verdoppelungsstrategie implementiert wird, sind die Gesamtkosten für N Operationen O(N). Beweis: Genauso wie bei Stacks. Bemerkung: Bei der Verdoppelungsstrategie gilt weiter: Der gesamte Platzbedarf ist O(k), wenn k die maximale je erreichte Länge der Queue ist. FG KTuEA, TU Ilmenau AuD 1.0.008

Einfachste Datenstrukturen für (endliche) Mengen Modelliere: Endliche Mengen über D. Intuitive Aufgabe: Speichere eine veränderliche Menge S D, S endlich, mit Operationen: Initialisierung: S ; ( anfangs ist S leer ) Suche: x S?; ( teste ob x in S ist ) Hinzufügen: S S {x}; ( füge x zu S hinzu ) Löschen: S S {x}. ( entferne x aus S ) FG KTuEA, TU Ilmenau AuD 1.0.008 5

1. Signatur: Datentyp Dynamische Menge Sorten: Operationen: Elements Sets Boolean empty: Sets insert: Sets Elements Sets delete: Sets Elements Sets member: Sets Elements Boolean member : englisch für Element (einer Menge). Statt member heißt die Operation oft auch lookup. FG KTuEA, TU Ilmenau AuD 1.0.008 6

Datentyp Dynamische Menge. Mathematisches Modell: Modellierung einer Menge als endliche Menge von Objekten: Sorten: Elements: (nichtleere) Menge D (Parameter) Sets: P < (D) = {S D S endlich} Boolean: {true, false} FG KTuEA, TU Ilmenau AuD 1.0.008 7

Operationen: Datentyp Dynamische Menge empty() = insert(s, x) := S {x} delete(s, x) := S {x} { true, falls x S member(s, x) := false, falls x / S FG KTuEA, TU Ilmenau AuD 1.0.008 8

Beachte: Datentyp Dynamische Menge Ganz nebenbei wird das Verhalten des Datentyps bei den Sonderfällen bei insert(s, x) ist x schon in S bei delete(s, x) ist x nicht in S ohne Möglichkeit von Missverständnissen spezifiziert. FG KTuEA, TU Ilmenau AuD 1.0.008 9

Implementierungsmöglichkeiten (A) Einfach verkettete Liste oder Array mit Wiederholung : {1,, 5, 7, 11} darstellbar als list: bzw. 5 1 7 11 7 1 5 1 7 h 11 7 * * * m * * * * pegel: h FG KTuEA, TU Ilmenau AuD 1.0.008 50

Operationen: empty: erzeuge leere Liste / leeres Array A[1..m] member(x): durchsuche Liste / Array nach (erstem Auftreten von) x insert(x): füge x vorne in Liste ein bzw. füge x rechts von der Pegelposition in Array ein delete(x): suche und entferne alle Vorkommen von x in Liste bzw. Array Wie vermeidet man das Entstehen von Lücken im Array? Wenn A[j] zu entfernen ist: A[j] A[pegel]; pegel--; (Vorsicht: Nun erneut testen, ob A[j] = x ist.) FG KTuEA, TU Ilmenau AuD 1.0.008 51

Operationen mit Zeitbedarf h = gegenwärtige Pegelhöhe/Listenlänge empty: erzeuge leere Liste / leeres Array A[1..m] O(1) member(x): durchsuche Liste / Array nach (erstem Auftreten von) x O(h) insert(x): füge x vorne in Liste ein bzw. füge x rechts von der Pegelposition in Array ein O(1) delete(x): suche und entferne alle Vorkommen von x in Liste bzw. Array O(h) Nachteil: Wenn sehr oft schon vorhandene Elemente eingefügt werden, kann der Umfang der Liste viel größer als S werden, mit entsprechenden Auswirkungen auf Platzbedarf und Zeitaufwand. FG KTuEA, TU Ilmenau AuD 1.0.008 5

(B) Einfach verkettete Liste oder Array ohne Wiederholung: Mögliche Darstellung der Menge {1,, 3, 5, 7, 8, 11}: list: 5 3 1 7 11 8 bzw. 1 5 3 1 7 11 8 h * * * m * * * * pegel: h Variable pegel enthält stets S. FG KTuEA, TU Ilmenau AuD 1.0.008 53

(B) Einfach verkettete Liste oder Array ohne Wiederholung: Vorteil: Platz für S D ist genau S Array-/Listeneinträge. Nachteil: Bei insert, delete, member jeweils lineare Suche nötig. Rechenaufwand in allen Fällen Θ( S ). FG KTuEA, TU Ilmenau AuD 1.0.008 5

(C) Einfach verkettete Liste oder Array aufsteigend sortiert nur möglich bei Vorhandensein von Sortierschlüsseln aus (U, <) in jedem x D: key : D U. In Beispielen: D = U, key(x) = x. Darstellung der Menge {1,, 3, 5, 7, 8, 11} über D = U = N: list: bzw. 1 3 5 7 8 11 1 h 1 3 5 7 8 11 * * * m * * * * pegel: h Variable pegel enthält stets S. FG KTuEA, TU Ilmenau AuD 1.0.008 55

Einfach verkettete Liste aufsteigend sortiert: Vorteil: Kann Suche nach x abbrechen, sobald ein Listeneintrag x erreicht wird. Mittlere Anzahl von Vergleichen bei Suche nach einem der Einträge a 1 < < a n : wenn für jedes i gilt: Pr(x = a i ) = 1 n (1 + + 3 + + n) 1 n = n + 1. FG KTuEA, TU Ilmenau AuD 1.0.008 56

Mittlere Anzahl von Vergleichen bei Suche nach einem x / {a 1,..., a n } (1 Vergleich für Entscheidung zwischen <, =, >): wenn gilt: für jedes i, i n, ist Pr(a i 1 < x < a i ) = 1 n+1 und Pr(x < a 1 ) = Pr(a n < x) = 1 n+1 : (1 + + 3 + + n + n) 1 n + 1 < n + 1. Dies gilt ebenfalls für die Einfüge- und die Lösch-Operation. FG KTuEA, TU Ilmenau AuD 1.0.008 57

Array, aufsteigend sortiert: 5 10 17 6 37 50 65 Nachteil: insert, delete: Verschieben vieler Elemente nötig, um die Ordnung zu erhalten und dabei das Entstehen von Lücken zu vermeiden. Zeitaufwand: Θ( S ) Vorteil: member: Kann binäre Suche benutzen. FG KTuEA, TU Ilmenau AuD 1.0.008 58

Gesehen gekonnt? Spezifikation einfacher Datentypen mittels Signatur und mathematischem Modell Listenimplementierung von Stacks und Queues Arrayimplementierung von Stacks und Queues Korrektheitsbegriff für Implementierungen Korrektheitsbeweise (Induktion) Verdoppelungsstrategie mit (amortisierter) Analyse Spezifikation und einfache Implementierungen für den Datentyp (endliche) Menge Aufwandsbetrachtungen für Datenstrukturen FG KTuEA, TU Ilmenau AuD 1.0.008 59