Presentation is loading. Please wait.

Presentation is loading. Please wait.

QUEUES What are Queues? Creating a Queue Enqueuing and Dequeuing Testing for an Empty Queue.

Similar presentations


Presentation on theme: "QUEUES What are Queues? Creating a Queue Enqueuing and Dequeuing Testing for an Empty Queue."— Presentation transcript:

1 QUEUES What are Queues? Creating a Queue Enqueuing and Dequeuing Testing for an Empty Queue

2 © 2006 Pearson EducationQueues2 of 32 Queues Similar to stacks, but items are removed in different order Useful in different situations: –stacks used for activation records –queues used for event processing Information retrieved in same order in which it was stored –FIFO: first in, first out Examples: –standing in line Like stacks, queues store Object s –again, use generics to restrict class types of data passed to queue October 27, 2005

3 © 2006 Pearson EducationQueues3 of 32 Enqueuing and Dequeuing Enqueuing: adds a node Dequeuing: removes a node BEFORE ENQUEUING AFTER ENQUEUING person removed from queue BEFORE DEQUEUING AFTER DEQUEUING head of queue tail of queue person to add head of queue tail of queue 12341234 12341234

4 © 2006 Pearson EducationQueues4 of 32 Syntax: The Movie Line A movie line queue may be instantiated to only accept object of type person: Right now Person only stores _myName –subclasses might store more information (phone number, favorite foods, pictures, etc.) Different subclasses of people can be stored in a queue –we use generics to only allow Person s –Men and Women could be subclasses of Person –both types of people would be able to stand in our line Number of plates on dispenser can vary from 0 to... public class Person { private String _myName; public Person (String name) { _myName = name; } public String getName() { return _myName; } } October 27, 2005

5 © 2006 Pearson EducationQueues5 of 32 Special Notes In a stack, everything is added and removed from top Bottom : –was never removed –handled special cases when stack was empty Queues require two special nodes: one to mark head of queue and one to mark tail Queue dequeues via head node; enqueues via tail node. Neither head nor tail can be removed Unlike bottom of stack, which had no references, tail node needs to communicate with last internal node of queue in order to give it reference to newly enqueued node Head node needs reference to next node in order to dequeue it October 27, 2005

6 © 2006 Pearson EducationQueues6 of 32 The Complete Queue Let’s look at a complete queue. Note that Queue class contains references to head and tail nodes –head and tail are permanent parts of queue HeadNode Node _next InternalNode ElementType _data Node _next InternalNode ElementType _data Node _next InternalNode ElementType _data Node _next Queue HeadNode _head TailNode _tail TailNode Node _prev... October 27, 2005

7 © 2006 Pearson EducationQueues7 of 32 Example: Enqueue (1 of 3) Let’s look at an example of enqueuing. This is our empty queue: Note that head and tail nodes point to each other HeadNode Node _next Queue HeadNode _head TailNode _tail TailNode Node _prev October 27, 2005

8 © 2006 Pearson EducationQueues8 of 32 Example: Enqueue (2 of 3) Here’s our queue right BEFORE one enqueue: Note: We haven’t forgotten about Queue class that contains head and tail; we just didn’t draw it for simplicity A new Internal Node is instantiated, “Mike” is the data stored in _myName References that have been newly set or changed and new instances shown in red HeadNode Node _next TailNode Node _prev InternalNode ElementType _data Node _next Person Mike October 27, 2005

9 © 2006 Pearson EducationQueues9 of 32 Example: Enqueue (3 of 3) Here’s our queue after the second enqueue (new node is added at end): Once again, reference in red are the only ones queue needs to change HeadNode Node _next TailNode Node _prev InternalNode ElementType _data Node _next Person Sara InternalNode ElementType _data Node _next Person Mike October 27, 2005

10 © 2006 Pearson EducationQueues10 of 32 Let’s Dequeue Note here’s our list after one dequeue (node closest to head node is removed): This looks simpler than enqueue of empty queue: only one reference needed to change HeadNode Node _next TailNode Node _prev InternalNode ElementType _data Node _next Person Sara October 27, 2005 InternalNode ElementType _data Node _next Person Mike Garbage Collected!

11 © 2006 Pearson EducationQueues11 of 32 A Tricky Dequeue Let’s dequeue the last internal node: Now there are two links that need to change: HeadNode Node _next TailNode Node _prev October 27, 2005 InternalNode ElementType _data Node _next Person Sara boundary case: dequeue will need to behave differently when removing last internal node Garbage Collected!

12 © 2006 Pearson EducationQueues12 of 32 Empty? We also need to be able to check if Queue representing our movie line is empty In stack, isEmpty() was easy to write -- Stack asked top node and InternalNode returned false; Bottom returned true Queue will always refer to HeadNode and TailNode only. How can we check isEmpty() ? Queue will ask HeadNode, which will in turn ask _next node. As before, InternalNode will return false and TailNode will return true Very similar to Stack, but with one extra level of delegation October 27, 2005

13 © 2006 Pearson EducationQueues13 of 32 Nodes Before we can build queue, we need to define smart nodes which make it up Once again, we need generic superclass from which all concrete nodes will inherit enqueue and dequeue need to reset some references. We will define set methods for all nodes to help them do this Three different types of nodes hold different references and will react very differently to these methods, but –we still want to be able to call these methods using reference to generic node –so, we have to declare their common methods in superclass - polymorphism again October 27, 2005

14 © 2006 Pearson EducationQueues14 of 32 Generic Nodes Code for generic node: setNext and setPrevious are empty methods which do nothing by default isEmpty will return true for tail node, false for internal nodes Node superclass declares dequeue message, but not enqueue : –in stack, Node declared pop message, but not push –every type of object in queue responds differently to dequeue message so is declared abstract in superclass –enqueue is specific to TailNode so declare it there // generic Queue Node public abstract class Node { public void setNext(Node newNextNode) {} public void setPrevious(Node newPrevNode) {} abstract public boolean isEmpty(); abstract public Node dequeue (ObjectHolder result); } October 27, 2005

15 © 2006 Pearson EducationQueues15 of 32 Head Node Head node is responsible for starting dequeue because queue removes things from front: HeadNode inherits setPrevious method but does not redefine it, since head node has no _previous reference; instead redefines setNext which it uses to jump around dequeued node to reference new first node We’ve left most of these methods undefined; we’ll define them later public class HeadNode extends Node { private Node _next; public HeadNode() {... } // methods redefined from superclass public Node dequeue (Holder result) {...} public boolean isEmpty() {...} public void setNext(Node newNextNode){ _next = newNextNode; } } October 27, 2005

16 © 2006 Pearson EducationQueues16 of 32 Tail Node Conversely, tail node handles enqueue : TailNode inherits setNext method but does not redefine it, since tail node has no _next reference; instead redefines setPrevious Since tail node responds to dequeue message, must redefine it We will define the rest of these methods later public class TailNode extends Node { private Node _prev; public TailNode(Node newPrevNode) {... } // method specific to TailNode public void enqueue(ElementType newData) {...} // methods redefined from superclass public Node dequeue (Holder result) {...} public void setPrevious(Node newPrevNode) { _prev = newPrevNode; } } October 27, 2005

17 © 2006 Pearson EducationQueues17 of 32 Internal Nodes Internal nodes need references to data they store and to next node in queue: Like head node, internal nodes redefine setNext method setPrevious does nothing (as in superclass), so it doesn’t need to be redefined public class InternalNode extends Node { private ElementType _data; private Node _next; public InternalNode(ElementType newData, Node newNextNode) {...} // methods redefined from superclass public Node dequeue (Holder result) {...} public void setNext(Node newNextNode) { _next = newNextNode; } } October 27, 2005

18 © 2006 Pearson EducationQueues18 of 32 Queue Now that we know what nodes look like, we can begin to code our queue: Queue has to keep references to both HeadNode and TailNode so it can tell _tail to enqueue and _ head to dequeue public class Queue { private Node _head; private TailNode _tail; // instantiates HeadNode and TailNode public Queue() { //note asymmetric reference setting! why? _head = new HeadNode (); //set in constructor _tail = new TailNode (_head); //set explicitly _head.setNext(_tail); } public void dequeue() { // code to follow... } public boolean isEmpty() { // code to follow... } public void enqueue(ElementType newData) { // code to follow... } } October 27, 2005

19 © 2006 Pearson EducationQueues19 of 32 Node Constructors So far, we’ve defined Queue to construct instances of HeadNode and TailNode. InternalNode s will be created during enqueuing as they were during pushes of stack public class HeadNode extends Node { //head doesn’t set its _next here public HeadNode() { super(); } //rest of class... } public class TailNode extends Node { //tail does set its _previous here public TailNode(Node newPrevNode){ super(); _prev = newPrevNode; } //rest of class... } public class InternalNode extends Node { public InternalNode(ElementType newData, Node newNextNode) { super(); _next = newNextNode; _data = newData; } //rest of class... } October 27, 2005

20 © 2006 Pearson EducationQueues20 of 32 Enqueue Queue delegates enqueue message to tail node, telling it to add new internal node before it: TailNode ’s enqueue method: –creates new internal node, passing it data to store and reference to tail which it will store in its _next –reassigns _next reference of its previous node to point to new node –resets its own _prev reference to new node Let’s see a picture.... public class Queue { public void enqueue(ElementType newData) { _tail.enqueue(newData); }... } public class TailNode extends Node{ public void enqueue(ElementType newData) { InternalNode newPrevNode = new InternalNode (newData, this); _prev.setNext(newPrevNode); _prev = newPrevNode; }... } October 27, 2005

21 © 2006 Pearson EducationQueues21 of 32 Example: Enqueue (1 of 2) Before enqueue : Tail creates new internal node, sending it references to data and itself; reference to new node stored in newPrevNode HeadNode Node _next TailNode Node _prev InternalNode ElementType _data Node _next Person Sara HeadNode Node _next TailNode Node _prev Person Sara newData to enqueue InternalNode newPrevNode = newPrevNode October 27, 2005 new InternalNode (newData, this);

22 © 2006 Pearson EducationQueues22 of 32 Example: Enqueue (2 of 2) Tail tells its previous node (head in this case) to reset its _next reference to newPrev Tail resets its own _prev reference HeadNode Node _next TailNode Node _prev InternalNode ElementType _data Node _next Person Sara HeadNode Node _next TailNode Node _prev InternalNode ElementType _data Node _next Person Sara newPrevNode October 27, 2005 _prev.setNext(newPrevNode); _prev = newPrevNode;

23 © 2006 Pearson EducationQueues23 of 32 Syntax: Dequeue (1 of 3) dequeue removes internal node at head of queue and returns its data Queue ’s dequeue method: –creates Holder (remember from stacks lecture - - why we use one?) –sends dequeue message to head node, passing it reference to Holder –returns data stored in Holder public class Queue { public ElementType dequeue() { Holder result = new Holder (); _head.dequeue(result); return result.getObject(); }... } October 27, 2005

24 © 2006 Pearson EducationQueues24 of 32 Syntax: Dequeue (2 of 3) HeadNode passes on dequeue message to next node in list, either internal or tail node: Just as with Stack ’s internal nodes, Queue ’s InternalNode s update Holder to reference their _data and return reference to their next node: public class HeadNode extends Node{ // next (internal) node assigns its data to // result and returns its next; tail “no-ops” public Node dequeue( Holder result) { _next = _next.dequeue(result); // tell next to point its previous to me. // Only for tailNode; internal node no-ops _next.setPrevious(this); return this; }... } public class InternalNode extends Node { public Node dequeue( Holder result) { result.setObject(_data); return _next; }... } October 27, 2005

25 © 2006 Pearson EducationQueues25 of 32 Syntax: Dequeue (3 of 3) TailNode s don’t have _data or _next reference, so they just return reference to themselves: Note similarities to Stack! Now, let’s hand simulate our code... public class TailNode extends Node{ public Node dequeue( Holder result) { return this; }... } October 27, 2005

26 © 2006 Pearson EducationQueues26 of 32 Example: Dequeue (1 of 3) From class Queue : result = new Holder (); HeadNode Node _next TailNode Node _prev InternalNode ElementType _data Node _next Person Sara InternalNode ElementType _data Node _next Person Mike Holder ElementType _data null result October 27, 2005

27 © 2006 Pearson EducationQueues27 of 32 Example: Dequeue (2 of 3) From HeadNode : _next = _next.dequeue(result); From InternalNode : result.setObject(_data); From InternalNode: return _next; From HeadNode: _next.setPrevious(this); Let’s see this simulated: HeadNode Node _next TailNode Node _prev InternalNode ElementType _data Node _next Person Sara InternalNode ElementType _data Node _next Person Mike Holder ElementType _data result Internal Node about to be garbage collected October 27, 2005

28 © 2006 Pearson EducationQueues28 of 32 Example: Dequeue (3 of 3) What happens if we call dequeue on empty queue? Queue will not change –Holder will contain no data after TailNode ’s dequeue method returns itself –HeadNode ’s _next reference will still point to tail because tail’s dequeue method returns reference to itself Cleaner code might be to check if queue is empty before dequeue-ing October 27, 2005

29 © 2006 Pearson EducationQueues29 of 32 Empty (1 of 2) As with stack, queue does not know if it is isEmpty, so it must delegate: HeadNode does not know either, so must ask _next node: public class Queue { public boolean isEmpty() { return _head.isEmpty(); }... } public class HeadNode extends Node{ public boolean isEmpty() { return _next.isEmpty(); }... } October 27, 2005

30 © 2006 Pearson EducationQueues30 of 32 Empty (2 of 2) If HeadNode sends isEmpty message to InternalNode, then queue has at least one element: If HeadNode sends isEmpty message to TailNode, then queue must be empty (no InternalNode s): public class InternalNode extends Node { public boolean isEmpty() { return false; }... } public class TailNode extends Node{ public boolean isEmpty() { return true; }... } October 27, 2005

31 © 2006 Pearson EducationQueues31 of 32 And we’re done! HAPPY QUEUING! JUST QUEUE IT! QUEUE, BABY, QUEUE Q October 27, 2005

32 © 2006 Pearson EducationQueues32 of 32 October 27, 2005


Download ppt "QUEUES What are Queues? Creating a Queue Enqueuing and Dequeuing Testing for an Empty Queue."

Similar presentations


Ads by Google