Einleitung Stack Queue Einleitung Stack Queue Gliederung Algorithmen und Datenstrukturen – Einführung Abstrakte Datentypen (ADT) I 1 Einleitung 2 Stack Stacks im Alltag ADT Stack Implementation 3 Queue Queues im Alltag ADT Queue Implementation D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg Winter 2008/2009, 23. November 2008 D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Abstrakte Datentypen Abstrakte Datentypen in Haskell 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 durch die Menge der auf ihnen zugelassenen Operationen (Konstruktoren, Selektoren, Prädikate) definiert diese werden auch als das Interface des ADT bezeichnet 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 2008/2009 . . . 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 2008/2009 . . . Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation Stack: Alltagsbeispiele Stack . . . dt. Stapel im folgenden einige Beispiele aus dem Alltag D. Rösner AuD 2008/2009 . . . 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 2008/2009 . . . 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 2008/2009 . . . Quelle: http://www.pacificcatering.com.au/files/categories/md/ D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack 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 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 s.a. [RL99], Ch. 5 D. Rösner AuD 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack 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 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 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Bedeutung von ’pop’ als engl. Verb (aus WordNet 2.0): Bedeutung von ’pop’ als engl. Verb (aus WordNet 2.0) (cont.): The verb pop has 13 senses (first 4 from tagged texts) 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") 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 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack ADT Stack die Modul-Definition (s.a. [RL99], Ch. 5): Implementation mit einem Konstruktor module Stack(Stack,push,pop,top,emptyStack,stackEmpty) where emptyStack:: Stack a stackEmpty:: Stack a -> Bool push :: a-> Stack a -> Stack a pop :: Stack a -> Stack a top :: Stack a -> a D. Rösner AuD 2008/2009 . . . data Stack a = EmptyStk | Stk a (Stack a) emptyStack = EmptyStk stackEmpty EmptyStk = True stackEmpty _ = False D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Implementation mit einem Konstruktor (cont.) Alternative Implementation durch Liste: newtype Stack a = Stk [a] 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 emptyStack = Stk [] stackEmpty (Stk []) = True stackEmpty (Stk _ ) = False D. Rösner AuD 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack ADT Stack Alternative Implementation durch Liste (cont.): eine mit deriving gewonnene show-Funktion würde die Implementation offenlegen push x (Stk xs) = Stk (x:xs) daher Definition einer eigenen Darstellung für Stacks für die Implementation mit Konstruktor: pop (Stk []) = error "pop from an empty stack" pop (Stk (_:xs)) = Stk xs Beispiel top (Stk []) = error "top from an empty stack" top (Stk (x:_)) = x 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 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Stacks im Alltag ADT Stack Implementation ADT Stack Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Definition einer eigenen Darstellung für Stacks für die Implementation mit Liste: Queue . . . dt. Schlange (im Sinne von Warteschlange) Beispiel im folgenden einige Beispiele aus dem Alltag 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 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Queue: Alltagsbeispiele Quelle: http://www.istockphoto.com/ D. Rösner Queue: Alltagsbeispiele AuD 2008/2009 . . . Waiting queue in front of the Science Express Quelle: www.science-express.com/.../2008/02/amit5.jpg D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue Queue: Alltagsbeispiele 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 Quelle: http://www.cartoonstock.com/newscartoons/cartoonists/kty/lowres/ktyn35l.jpg D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue D. Rösner AuD 2008/2009 . . . 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 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 s.a. [RL99], Ch. 5.3 bzw. [GT01], Ch. 4.2 D. Rösner AuD 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT 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 Einleitung Stack Queue :: :: :: :: :: Queue a Queue a -> a -> Queue Queue a -> Queue a -> Bool a -> Queue a Queue a a Implementation durch Liste: newtype Queue a deriving Show emptyQueue = Q [a] = Q [] queueEmpty (Q []) queueEmpty (Q _ ) = True = False D. Rösner AuD 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue 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 2008/2009 . . . 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 2008/2009 . . . Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue 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 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) 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 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Einleitung Stack Queue Queues im Alltag ADT Queue Implementation ADT Queue ADT Queue Alternative Implementation durch ein Paar von Listen (cont.): Alternative Implementation durch ein Paar von Listen (cont.): queueEmpty (Q ([],[])) = True queueEmpty _ = False Definition der gedruckten Darstellung in Analogie zu der bei der Listenimplementation durch deriving abgeleiteten emptyQueue = Q ([],[]) front (Q ([],[])) = error "front:empty queue" front (Q ([],ys)) = last ys front (Q (x:xs,ys)) = x D. Rösner AuD 2008/2009 . . . instance (Show a) => Show (Queue a) where showsPrec p (Q (front, rear)) str = showString "Q " (showList (front ++ reverse rear) str) D. Rösner AuD 2008/2009 . . . Einleitung Stack Queue Queues im Alltag ADT Queue Implementation Literatur: 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 2008/2009 . . .