Einleitung Stack Queue Algorithmen und Datenstrukturen I Abstrakte Datentypen D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg c Winter 2009/10, 22. November 2009, 2009/10 D.Rösner D. Rösner AuD I 2009/10 . . . 1 Einleitung Stack Queue Gliederung 1 Einleitung 2 Stack Stacks im Alltag ADT Stack Implementation 3 Queue Queues im Alltag ADT Queue Implementation D. Rösner AuD I 2009/10 . . . 2 Einleitung Stack Queue Abstrakte Datentypen abstrakte Datentypen kurz oft nur ADT genannt sind im Unterschied zu den bisher betrachteten – konkreten – Datentypen nicht an eine bestimmte Repräsentation gebunden ADTs werden implizit definiert durch die Menge der auf ihnen zugelassenen Operationen: Konstruktoren, Selektoren, Prädikate diese werden auch als das Interface des ADT bezeichnet ... D. Rösner AuD I 2009/10 . . . 3 Einleitung Stack Queue Abstrakte Datentypen abstrakte Datentypen ... nur das Interface wird “Nutzern“ offengelegt die interne Struktur – die sog. Implementierung – des ADT bleibt “verborgen“ (Kapselung, ’information hiding’) und könnte jederzeit geändert werden solange das Interface unverändert bleibt, ist Code, der den ADT nutzt, davon nicht betroffen m.a.W.: ADTs dienen der Modularisierung D. Rösner AuD I 2009/10 . . . 4 Einleitung Stack Queue Abstrakte Datentypen in Haskell in Haskell können ADTs durch Haskell-Module realisiert werden ein Modul in Haskell definiert eine Menge von Funktionen und Datentypen in einer geschlossenen Umgebung ein Modul kann alle oder auch nur einige ausgewählte seiner Definitionen exportieren definiert wird ein Modul in Haskell durch module <name> (<exportliste>) where <definitionen> D. Rösner AuD I 2009/10 . . . 5 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Stack . . . dt. Stapel im folgenden einige Beispiele aus dem Alltag D. Rösner AuD I 2009/10 . . . 7 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation Stack: Alltagsbeispiele Quelle: http://www.fromoldbooks.org/pictures-of-old-books/pages/ D. Rösner AuD I 2009/10 . . . 8 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation Stack: Alltagsbeispiele Quelle: http://www.rotten.com/library/culture/the-simpsons/homer-pez-dispenser.jpg D. Rösner AuD I 2009/10 . . . 9 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation Stack: Alltagsbeispiele Quelle: http://www.pacificcatering.com.au/files/categories/md/ D. Rösner AuD I 2009/10 . . . 10 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack abstrakter Datentyp Stack Ein Stack ist eine homogene Sammlung von Objekten, auf denen zwei zentrale Operationen definiert sind: Definition push x s füge x als neues oberstes Element in den Stack s ein und gib den veränderten Stack mit x als oberstem Element (sog. top) zurück pop s entferne das aktuelle oberste Element vom Stack und gib den veränderten Stack ohne x als oberstem Element als Wert zurück; Fehler, falls Stack leer s.a. [RL99], Ch. 5 D. Rösner AuD I 2009/10 . . . 12 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack abstrakter Datentyp Stack Stack realisiert das LIFO-Prinzip: last-in, first-out weitere Definitionen: das oberste Element eines Stacks s wird durch den Selektor top s geliefert (dieses bleibt aber auf dem Stack) mit dem Konstruktor emptyStack wird ein leerer Stack kreiert das Prädikat stackEmpty prüft, ob ein Stack noch Elemente enthält oder nicht manchmal kann auch noch mit size die Anzahl der Elemente auf dem Stack erfragt werden s.a. [RL99], Ch. 5 bzw. [GT01], Ch. 4 D. Rösner AuD I 2009/10 . . . 13 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack “Stacks and queues are among the simplest of all data structure, but are also among the most important.“ ([GT01], p. 136) wegen ihrer Bedeutung oft sogar in Hardware in den sog. Mikroinstruktionen in der CPU implementiert zentrales Element in vielen Programmierumgebungen, so z.B. in Hugs, aber auch in der Java Virtual Machine (JVM) s.a. [GT01], Ch. 4 D. Rösner AuD I 2009/10 . . . 14 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Beispiele für Verwendung von Stacks: Stack mit offenen Frames verschachtelter (rekursiver) Aufrufe von Funktionen sog. Operandenstack beim Auswerten arithmetischer Ausdrücke wie ((a + b)*(c + d))/e Speichern kürzlich besuchter WWW-Seiten in einem Stack in einem Webbrowser Undo-Mechanismus in Texteditoren realisiert über einen Stack mit den Operationen zur Textänderung s.a. [GT01], Ch. 4 D. Rösner AuD I 2009/10 . . . 15 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Bedeutung von ’pop’ als engl. Verb (aus WordNet 2.0): The verb pop has 13 senses (first 4 from tagged texts) 1. (3) protrude, pop, pop out, bulge, bulge out, bug out, come out -(bulge outward; "His eyes popped") 2. (3) pop -- (hit a pop-fly; "He popped out to shortstop") 3. (1) pop -- (make a sharp explosive noise; "The cork of the champagne bottle popped") 4. (1) pop -- (fire a weapon with a loud explosive noise; "The soldiers were popping") 5. pop -- (cause to make a sharp explosive sound; "He popped the champagne bottle") 6. crop up, pop up, pop -- (appear suddenly or unexpectedly; "The farm popped into view as we turned the corner"; "He suddenly popped up out of nowhere") D. Rösner AuD I 2009/10 . . . 16 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Bedeutung von ’pop’ als engl. Verb (aus WordNet 2.0) (cont.): 7. pop -- (put or thrust suddenly and forcefully; "pop the pizza into the microwave oven"; "He popped the petit-four into his mouth") 8. pop -- (release suddenly; "pop the clutch") 9. pop -- (hit or strike; "He popped me on the head") 10. toss off, pop, bolt down, belt down, pour down, down, drink down, kill -- (drink down entirely; "He downed three martinis before dinner"; "She killed a bottle of brandy that night"; "They popped a few beer after work") 11. pop -- (take drugs, especially orally; "The man charged with murder popped a valium to calm his nerves") 12. pop -- (cause to burst with a lound, explosive sound; "The child popped the balloon") 13. pop -- (burst open with a sharp, explosive sound; "The balloon popped"; "This popcorn pops quickly in the microwave oven") D. Rösner AuD I 2009/10 . . . 17 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack die Modul-Definition (s.a. [RL99], Ch. 5): module Stack(Stack,push,pop,top,emptyStack,stackEmpty) where emptyStack:: stackEmpty:: push :: a -> pop :: Stack top :: Stack Stack a Stack a -> Bool Stack a -> Stack a a -> Stack a a -> a D. Rösner AuD I 2009/10 . . . 19 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Implementation mit einem Konstruktor data Stack a = EmptyStk | Stk a (Stack a) emptyStack = EmptyStk stackEmpty EmptyStk = True stackEmpty _ = False D. Rösner AuD I 2009/10 . . . 20 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Implementation mit einem Konstruktor (cont.) push x s = Stk x s pop EmptyStk = error "pop from an empty stack" pop (Stk _ s) = s top EmptyStk = error "top from an empty stack" top (Stk x _) = x D. Rösner AuD I 2009/10 . . . 21 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Alternative Implementation durch Liste: newtype Stack a = Stk [a] emptyStack = Stk [] stackEmpty (Stk []) = True stackEmpty (Stk _ ) = False D. Rösner AuD I 2009/10 . . . 22 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Alternative Implementation durch Liste (cont.): push x (Stk xs) = Stk (x:xs) pop (Stk []) = error "pop from an empty stack" pop (Stk (_:xs)) = Stk xs top (Stk []) = error "top from an empty stack" top (Stk (x:_)) = x D. Rösner AuD I 2009/10 . . . 23 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack eine mit deriving gewonnene show-Funktion würde die Implementation offenlegen daher Definition einer eigenen Darstellung für Stacks für die Implementation mit Konstruktor: Beispiel instance (Show a) => Show (Stack a) where showsPrec p EmptyStk str = showChar ’-’ str showsPrec p (Stk x s) str = shows x (showChar ’|’ (shows s str)) D. Rösner AuD I 2009/10 . . . 24 Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Definition einer eigenen Darstellung für Stacks für die Implementation mit Liste: Beispiel instance (Show a) showsPrec p (Stk showsPrec p (Stk = shows x => Show (Stack a) where []) str = showChar ’-’ str (x:xs)) str (showChar ’|’ (shows (Stk xs) str)) D. Rösner AuD I 2009/10 . . . 25 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Queue . . . dt. Schlange (im Sinne von Warteschlange) im folgenden einige Beispiele aus dem Alltag D. Rösner AuD I 2009/10 . . . 27 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Queue: Alltagsbeispiele Quelle: http://www.istockphoto.com/ D. Rösner AuD I 2009/10 . . . 28 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Queue: Alltagsbeispiele Waiting queue in front of the Science Express Quelle: www.science-express.com/.../2008/02/amit5.jpg D. Rösner AuD I 2009/10 . . . 29 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Queue: Alltagsbeispiele Quelle: http://www.cartoonstock.com/newscartoons/cartoonists/kty/lowres/ktyn35l.jpg D. Rösner AuD I 2009/10 . . . 30 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue abstrakter Datentyp Queue Eine Queue ist – ähnlich wie ein Stack – eine homogene Sammlung von Objekten, auf denen zwei zentrale Operationen definiert sind: Definition enqueue x q füge x als neues letztes Element ’hinten’ (rear) an die Queue q an und gib die veränderte Queue zurück dequeue q entferne das aktuelle erste Element (front) aus der Queue und gib die veränderte Queue als Wert zurück; Fehler, falls Queue leer s.a. [RL99], Ch. 5.3 D. Rösner AuD I 2009/10 . . . 32 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue abstrakter Datentyp Queue Queue realisiert das FIFO-Prinzip: first-in, first-out weitere Definitionen: das erste Element einer Queue q wird durch den Selektor front q geliefert (aber nicht aus der Queue entfernt) mit dem Konstruktor emptyQueue wird eine leere Queue kreiert das Prädikat queueEmpty prüft, ob eine Queue noch Elemente enthält oder nicht manchmal kann auch noch mit size die Anzahl der Elemente in der Queue erfragt werden s.a. [RL99], Ch. 5.3 bzw. [GT01], Ch. 4.2 D. Rösner AuD I 2009/10 . . . 33 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Beispiele für Verwendung von Queues: Behörden, Läden, Theater, aber auch Mensen, Prüfungsämer u.ä. bedienen ihre Kunden üblicherweise nach dem FIFO-Prinzip Queue als Datenstruktur geeignet für Verwaltung aller Arten von Transaktionen nach diesem Prinzip z.B. Verwaltung eingehender (telefonischer) Anfragen bei einem Reservierungssystem oder sonstigen Call-Center s.a. [GT01], Ch. 4.2 D. Rösner AuD I 2009/10 . . . 34 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue die Modul-Definition (s.a. [RL99], Ch. 5.3): module Queue(Queue,emptyQueue,queueEmpty, enqueue,dequeue,front) where emptyQueue queueEmpty enqueue dequeue front :: :: :: :: :: Queue a Queue a -> a -> Queue Queue a -> Queue a -> Bool a -> Queue a Queue a a D. Rösner AuD I 2009/10 . . . 36 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Implementation durch Liste: newtype Queue a deriving Show emptyQueue = Q [a] = Q [] queueEmpty (Q []) queueEmpty (Q _ ) = True = False D. Rösner AuD I 2009/10 . . . 37 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Implementation durch Liste (cont.): enqueue x (Q q) = Q (q ++ [x]) dequeue (Q (_:xs)) = Q xs dequeue (Q []) = error "dequeue: empty queue" front (Q (x:_)) = x front (Q []) = error "front: empty queue" D. Rösner AuD I 2009/10 . . . 38 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Implementation durch Liste (cont.): Nachteil dieser Implementation Aufwand für enqueue ist O(n) denn: ................................ ................................ ... alle anderen Operationen haben konstanten Aufwand (O(1)) D. Rösner AuD I 2009/10 . . . 39 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Alternative Implementation durch ein Paar von Listen: Idee: erste Liste repräsentiert den Anfangsteil der Queue, zweite den hinteren Teil in umgedrehter Ordnung an den hinteren Teil kann dann mit konstantem Aufwand angefügt werden wird der Anfangsteil der Queue leer, dann wird der hintere Teil (einmal) umgedreht und zum Anfangsteil gemacht D. Rösner AuD I 2009/10 . . . 40 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue wird für reverse eine Implementation mit linearem Aufwand verwendet, dann ist der durchschnittliche Aufwand über eine Sequenz von Queue-Operationen O(1), im schlechtesten Fall kann er aber O(n) betragen (vgl. [RL99], Ch. 5.3) D. Rösner AuD I 2009/10 . . . 41 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Alternative Implementation durch ein Paar von Listen (cont.): newtype Queue a = Q ([a],[a]) enqueue x (Q ([],[])) = Q ([x],[]) enqueue y (Q (xs,ys)) = Q (xs,y:ys) dequeue (Q ([],[])) = error "dequeue:empty queue" dequeue (Q ([],ys)) = Q (tail(reverse ys) , []) dequeue (Q (x:xs,ys)) = Q (xs,ys) D. Rösner AuD I 2009/10 . . . 42 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Alternative Implementation durch ein Paar von Listen (cont.): queueEmpty (Q ([],[])) = True queueEmpty _ = False emptyQueue = Q ([],[]) front (Q ([],[])) = error "front:empty queue" front (Q ([],ys)) = last ys front (Q (x:xs,ys)) = x D. Rösner AuD I 2009/10 . . . 43 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Alternative Implementation durch ein Paar von Listen (cont.): Definition der gedruckten Darstellung in Analogie zu der bei der Listenimplementation durch deriving abgeleiteten instance (Show a) => Show (Queue a) where showsPrec p (Q (front, rear)) str = showString "Q " (showList (front ++ reverse rear) str) D. Rösner AuD I 2009/10 . . . 44 Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Literatur: I Michael T. Goodrich and Roberto Tamassia. Data Structures and Algorithms in Java. John Wiley & Sons, New York, 2001. ISBN 0-471-38367-8; 2nd edition. Fethi Rabhi and Guy Lapalme. Algorithms – A Functional Programming Approach. Pearson Education Ltd., Essex, 1999. 2nd edition, ISBN 0-201-59604-0. D. Rösner AuD I 2009/10 . . . 45