1 / 36

Queues

Learn about Queues, access the least recently added item, and perform operations like adding, removing, and retrieving items efficiently. Explore Queue concepts with examples in Java.

Download Presentation

Queues

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Queues Ellen Walker CPSC 201 Data Structures Hiram College

  2. Queue • Process data in a “fair” way regarding wait time • Access only “least recently added” item • When “least recently added” item is removed, the former 2nd least recently added item becomes available! • Why is it called a queue? • Queue of people waiting for a bus • Queue of jobs waiting for a printer

  3. Operations on a Queue • Create an empty queue • Is the queue empty? (isEmpty) • Add a new item to the queue. (offer) • Remove the item that was least recently added (remove or poll) • Retrieve the item that was least recently added (peek or element)

  4. Removing & Retrieving Front Element • Removing front element • poll() - returns null if queue is empty • remove() - throws exception if queue is empty • Retrieving front element without removing • peek() - returns null if queue is empty • element() - throws exception if queue is empty

  5. Specification for a Queue Interface

  6. Example • Create an empty queue • Offer “A” • Offer “B” • Remove (returns A) • Offer “C” • Remove (returns B) • Peek (returns C)

  7. LIFO vs. FIFO • A queue is FIFO (first in, first out) • Queues are fair when someone has to wait • A stack is a LIFO (last in, first out) data structure • New addition makes older items inaccessible • Stacks model “interruptions” in the real world (including getting back to what was interrupted…)

  8. Reading and Printing a Line //A queue of characters Queue<Character> q = new LinkedList<Character>(); //Read a line (scIn is a Scanner for System.in) String theLine = scIn.nextLine(); for(int c=0;c<theLine.length();c++) q.offer(theLine.charAt(c)); //Print the characters while(!q.isEmpty()){ System.out.println (q.remove()); }

  9. Check a Palindrome with Queue and Stack boolean checkPalindrome(String theLine){ Stack<Character> s = new ArrayStack<Character>(); Queue <Character> q = new LinkedList<Character>(); //Put each character into both queue and stack for(int c=0;c<theLine.length();c++){ char ch = theLine.charAt(c); if(Character.isLetter(ch)){ //ignore space & punctuation s.push(Character.toLowerCase(ch)); //ignore case q.offer(Character.toLowerCase(ch)); } }

  10. Checking a Palindrome (continued) //Check that forward (queue) and reverse (stack) //sequence of characters is the same while((!s.empty() && !q.isEmpty()){ char left = q.remove(); char right = s.pop(); if(left != right) return false; } return true; //both stack & queue are guaranteed same size }

  11. Implementing Queues • Start with a representation of a list • Linked or array? • Need access to front (for removing only) • Need access to back (for inserting only)

  12. Java’s List Implementation • Java implements queue as a doubly-linked list (LinkedList class) • Doesn’t matter which end is which, but Java uses head as front, tail as rear • Allowing LinkedList to implement queue breaks the abstraction • Queue shouldn’t have iterators, size(), etc.

  13. Single Linked Implementation • Where should the front be? (easy to access & remove, inserting not necessary) • Where should the back be? (easy to insert, direct access and removal not necessary) • No real reason for either front or back to be anywhere but beginning or end of list.

  14. Solution • Since we need to update the item *before* the given item to delete (except special case at head of list), we should delete at the head. • Therefore, list head = queue front • List tail = queue back, but that’s ok because we’ll have the item before (old tail) for the insertion.

  15. Example (List Implementation) • Empty queue • Enqueue ‘a’, Enqueue ‘b’, Enqueue ‘c’ • Dequeue, Dequeue • Enqueue ‘z’ a b c c c z

  16. Class Definition (data fields) Public class ListQueue<E> extends AbstractQueue<E> implements Queue<E>{ private Node<E> front; private Node<E> rear; //Insert inner Node class from LinkedList here private int size; // not strictly necessary … };

  17. isEmpty & peek • //Is the Queue empty? public boolean IsEmpty() { return (front == null); } • //Get item from front public E peek() { if (isEmpty()) return null; else return front.data; }

  18. Offer • // offer (add to end of list) public boolean offer(E item){ Node newItem = new Node(item); if (isEmpty()) front = newItem; else rear.next = newItem; rear = newItem; }

  19. poll • //Dequeue and recover old front item Public E poll(){ E item = peek(); if (item == null) return null; //empty queue else{ front=front.next; if (front == null) rear = null; //removed last item } return item; }

  20. Array Implementation • Where should the front be? (easy to access & remove, inserting not necessary) • Where should the back be? (easy to insert, direct access and removal not necessary) • No real reason for either front or back to be anywhere but beginning or end of array.

  21. Array Implementation • Inserting at the beginning of the array would cause a great deal of shifting! Therefore, insert at end of array • Rear of queue is end of array • Front of queue is front of array • Remove by moving the front pointer (like top for stack) • Problem: once we’ve moved the front forward, we lose access to the space behind it!

  22. Solution • Use a “circular array” • Most of the time, it acts like a normal array • The item after element MAX-1 is element 0 • Use Mod (%) operation to implement this. • One more problem… • How do we tell an empty array from a full array? • When the back pointer is one slot behind the front pointer, i.e. (back+1)%MAX = front, the array is either empty or full!

  23. Empty vs. Full Array • Keep a count of the elements in the array • Minimal space cost (1 integer), some time for each update • Keep one element free. When the queue is empty, (back+1)%MAX = front. When the queue is full (back+2)%MAX = front. • Space cost is the size of 1 queue element. This can be (much) larger than an integer! • Keep a “full” flag • Space & time costs similar to option #1.

  24. Array Queue Implementation public class ArrayQueue<E> extends AbstractQueue<E> implements Queue<E> { private E[] theData; private int front, rear; private int size, capacity; //choice 1 … }

  25. Constructor & isEmpty • Constructor creates a new array Public ArrayQueue(int initCapacity) { theData = (E[]) new Object[capacity]); capacity = initCapacity; front = 0; rear = capacity–1; } • isEmpty uses size (really in abstractQueue) Public boolean isEmpty(){ return (size == 0); }

  26. Offer public boolean offer(Itemtype item){ if (size == capacity) reallocate(); rear = (rear+1) % capacity; theData[rear] = item; size++; return true; }

  27. Poll (and peek) Public E poll(){ if (isEmpty()) return null; E result = theData[front]; front = (front+1) %capacity; size--; return result; } //Peek is similar, but doesn’t change front or size.

  28. Reallocate • When the queue is full, make a new one (double size) and copy all the data Private void reallocate(){ //make new array int newCapacity = 2*capacity; E[] newData = (E[]) new Object[newCapacity]; int j=front; //continued on next slide

  29. Reallocate (continued) //copy data to new array int j=front; for int (x=0;x<size;x++){ newData[x] = theData[j]; j=(j+1)%capacity; } //reset variables front = 0; rear = size–1; theData = newData; } //end of reallocate

  30. Application: Simulation • Simulate a real-life situation • Make several simplifying assumptions • Time is divided into discrete time steps • One or more events happen at each time step • Arrival events (e.g. customer arrives at bank) -- comes from input (time of arrival) • Departure events (e.g. customer leaves bank) -- internally determined from when transaction begins and transaction time.

  31. Bank example with Queue • We want to measure how long customers wait at the bank. • When a customer arrives, an arrival event is processed. Since customers should be processed in order, they wait in a queue • Assume that each transaction takes a fixed amount of time. When time is up, the customer being processed leaves, and the next customer (front of the queue) takes their place.

  32. Using the Simulation for Decision Making • Vary the number of tellers - how does the wait time vary? • Consider different types of “teller transactions” with different transaction times • Should we have an “express lane”? • If we have multiple tellers, should each have its own queue?

  33. A simple pseudocode • Read the first arrival • For (time=0;time<max;time++){ • If it’s time for the first arrival • Process the arrival • Read the next arrival (assume only one arrival per time) • If there is a departure event at this time • Process the departure • }

  34. Two data structures • Event list • Sorted by event time • Includes arrivals and departures • List, not queue (why)? • Customer queue • Customers enter when they arrive if the teller is busy • Customer at front of queue “goes to the teller” when the previous customer departs

  35. Implementing the “teller” • We don’t need a specific data structure for the teller • When a customer “goes to the teller”, a departure event for that customer is created • Time of departure is based on estimated transaction time • When the departure event is processed, that customer “leaves the teller”, and a new customer will be taken from the front of the queue

  36. Searching a Graph with a Queue • Given connections among cities, find a path from A to B • Revise our stack algorithm to use a queue: q.offer (Start) for each city visible from q.peek() if the city is End, recover and return the path if the city is not already on the queue, mark city’s predecessor as q.peek() q.offer( the city ) q.remove().

More Related