CS Data Structures I Chapter 7 Queue I
2 Topics Introduction Queue Application Implementation Linked List Array ADT List
3 Queues A queue differs from a stack in that it follows the first-in-first-out (FIFO) principle. Inserting an item to the rear is known as "enqueueing". Removing an item from the front is known as "dequeueing". cashier Front of lineBack of line
4 Queues Linear, homogeneous structure Has First-In-First-Out (FIFO) behavior; Items added at one end and removed from the other end Middle elements are logically inaccessible Add/ Enqueue Remove/ Dequeue Back/RearFront/Head
5 Queue Applications Real-World Applications Buy a movie ticket Check out at a bookstore Cashier lines in any store Computer Science Applications OS task scheduling Print lines of a document Convert digit strings to decimal Shared resource usage (CPU, memory access, … )
6 ADT Queue Specification: Elements Homogeneous Linear Structure: Elements added to rear & removed from front
7 ADT Queue Specification: Operations Create an empty queue Destroy a queue Check if a queue is empty / Full Enqueue (Enq, Enque, Add, Insert): Adding new element at the back (rear) Dequeue (Deq, Deque, Remove, Serve): Deleting an element from the front Retrieve an element from a queue
8 Queue Applications Converting Digit Strings to Decimal Enter characters from the keyboard and retain them in order Assumption: No typing mistakes Blank spaces may precede or follow the digits Formula used: Initial value DigitSum = 0
9 Queue Applications Converting Digit Strings to Decimal Pseudocode // Convert digits in aQueue into decimal integer n // Get first digit, ignoring any leading blanks do { ch=queue.dequeue() } while ( ch is blank) // Assertion: ch contains first digit // Compute n from digits in queue n = 0; done = false; do {n = 10 * n + integer that ch represents if (! queue.isEmpty( ) ) ch=queue.dequeue() else done = true } while (! done and ch is a digit) // Assertion: n is result
10 Queue Applications Recognizing Palindromes Uses a queue & a stack Idea: 1. Insert the string in both queue & stack 2. Remove characters from both stack's Top & queue's Front, comparing them 3. Repeat until: a) Either the stack or the queue are empty String is a palindrome b) The character from the stack and the corresponding character from the queue are not similar String isn't a palindrome
11 Queue Applications Recognizing Palindromes Pseudocode IsPal(in str:string) : boolean // Determines whether String is a palindrome aQueue.createQueue ( ) // Create an empty queue aStack.createStack ( ) // Create an empty stack // Insert each character of String into both aQueue and aStack length = length of str for ( i = 1 through length) {nextChar = i th character of str aQueue.enqueue ( nextChar ) aStack.push(NextChar) } // end for // Compare aQueue with aStack charactersAreEqual = true; while ( ! aQueue.isEmpty() && charactersAreEqual) {aQueue.getFront ( queueFront ) aStack.getTop ( stackTop ) if ( queueFront equals stackTop) {aQueue.dequeue ( ) aStack.pop ( ) } elsecharactersAreEqual = false } // end while return charactersAreEqual
12 ADT Queue Implementation Possible implementations: Linked List-based Linear Circular Array-based Linear Circular ADT List-based
13 Linked List-Based Implementation More straightforward than array-based Possible options: Linear linked list Two external “ pointer ” (Front & Back) Circular linked list One “ pointer ” will be enough (Back)
14 Linked List Queue Implementation Linked List -Based Implementation: Option 1 Insertion to an empty list front = newNode back = newNode
15 Linked List Queue Implementation LL -Based Implementation: Option 1 Insertion to a non-empty list newNode.setNext ( NULL); Back.setNext (newNode); back = newNode Deletion temp = front front = front.getNext() temp.setNext ( NULL ) 2015 front 2684 back
16 Linked List Queue Implementation LL -Based Implementation: option 1 Deletion form a one-node (one item) queue If (front = back&&front!=null){ back = null front=null } form a non-empty, more than one item queue front = front.getNext()
17 Linked List Queue Implementation LL based Implementation: option 2 Insertion Into an empty queue newNode.setNext (newNode) back = newNode Into a non-empty queue newNode.setNext (back.getNext()) Back.setNext (newNode); back = newnode
18 Linked List Queue Implementation LL -Based Implementation: option 2 Deletion form a one-node (one item) queue Node front = back.getNext() If (front = back) back = NULL Front=null form a non-empty, more than one item queue Node front = back.getNext() Back.setNext ( front.getNext()) Front=null
19 Queue Interface public interface QueueInterface { public boolean isEmpty(); // Determines whether a queue is empty. // Precondition: None. // Postcondition: Returns true if the queue is empty; // otherwise returns false. public void enqueue(Object newItem) throws QueueException; // Adds an item at the back of a queue. // Precondition: newItem is the item to be inserted. // Postcondition: If the operation was successful, newItem // is at the back of the queue. Some implementations // may throw QueueException if newItem cannot be added to the queue. public Object dequeue() throws QueueException; // Retrieves and removes the front of a queue. // Precondition: None. // Postcondition: If the queue is not empty, the item that was added to the // queue earliest is returned and the item is removed. If the queue is empty, // the operation is impossible and QueueException is thrown.
20 Queue Interface (2) public void dequeueAll(); // Removes all items of a queue. // Precondition: None. // Postcondition: The queue is empty. public Object peek() throws QueueException; // Retrieves the item at the front of a queue. // Precondition: None. // Postcondition: If the queue is not empty, the item // that was added to the queue earliest is returned. // If the queue is empty, the operation is impossible // and QueueException is thrown. } // end QueueInterface
21 Queue Exception public class QueueException extends RuntimeException { public QueueException(String s) { super(s); } // end constructor } // end QueueException
22 LListQueue Implementation public class LListQueue implements QueueInterface { private Node lastNode; public LListQueue() { lastNode = null; } // end default constructor // queue operations: public boolean isEmpty() { return lastNode == null; } // end isEmpty public boolean isFull() { return false; } // end isFull public void dequeueAll() { lastNode = null; } // end dequeueAll
23 LListQueue Implementation (2) public void enqueue(Object newItem) { Node newNode = new Node(newItem); if(isFull()) throw new QueueException("QueueException on enqueue:"+ "queue full"); // insert the new node if (isEmpty()) { // insertion into empty queue newNode.setNext(newNode); } else { // insertion into nonempty queue newNode.setNext(lastNode.getNext()); lastNode.setNext(newNode); } // end if lastNode = newNode; // new node is at back } // end enqueue
24 LListQueue Implementation (3) public Object dequeue() throws QueueException { if (!isEmpty()) { // queue is not empty; remove front Node firstNode = lastNode.getNext(); if (firstNode == lastNode) { // special case? lastNode = null; // yes, one node in queue } else { lastNode.setNext(firstNode.getNext()); } // end if return firstNode.getItem(); } else { throw new QueueException("QueueException on dequeue:" + "queue empty"); } // end if } // end dequeue
25 LListQueue Implementation (4) public Object peek() throws QueueException { if (!isEmpty()) { // queue is not empty; retrieve front Node firstNode = lastNode.getNext(); return firstNode.getItem(); } else { throw new QueueException("QueueException on peek:" + "queue empty"); } // end if } // end peek } // end ListQueue
26 LListQueue Test public class LListQueueTest { public static void main(String[ ] args) { LListQueue aQueue = new LListQueue(); System.out.println("Enqueuing:"); for (int i = 0; i < 9; i++) { System.out.print(" "+i); aQueue.enqueue(new Integer(i)); } // end for System.out.println("\nDequeuing:"); for (int i = 0; i < 9; i++) { System.out.print(" "+aQueue.dequeue()); } // end for System.out.println(); } // end main } // QueueTest
27 Array-Based Queue Implementation Array-Based Implementation Fix-size Have the following definition final int MAZ_QUEUE = maxinum-size-of-queue; Object [] items; Int front; Int back;
28 Array-Based Queue Implementation 1. Linear Array implementation Front & Back are indexes in the array Initial condition: Front =0 & Back = -1 Initial state After 5 additions 04 FrontBack MAX_QUEUE -1 0 FrontBack MAX_QUEUE -1
29 Array-Based Queue Implementation 1. Linear Array implementation Back will point to the last added element Initial values: front = 0 back = -1 Insertion Increment back Insert item in item [ back ] Deletion Increment front Queue Empty Condition back < front Queue is Full back == MAX_QUEUE-1
30 Array-Based Queue Implementation 1. Linear Array implementation Problem: Rightward-Drifting: After a sequence of additions & removals, items will drift towards the end of the array Full if back==MAX_QUEUE-1, even only a few items 4749 FrontBack MAX_QUEUE -1 Rightward drifting
31 Array-Based Queue Implementation 1. Linear Array implementation Rightward drifting solutions Use a circular array: When Front or Back reach the end of the array, wrap them around to the beginning of the array Problem: Front & Back can't be used to distinguish between queue-full & queue-empty conditions
32 Array-Based Queue Implementation 2. Circular Array Implementation Back Front MAX_QUEUE -1 Back Front MAX_QUEUE -1 Back Front MAX_QUEUE Deletion and Insertion on the queue
33 Array-Based Queue Implementation 2. How to determine if queue is full or empty? Back 1 76 MAX_QUEUE -1 Front Back MAX_QUEUE -1 0 Front 0 Queue wiith one item Delete, queue becomes empty
34 Array-Based Queue Implementation 2. How to determine if queue is full or empty? Back 1 76 MAX_QUEUE -1 0 Front Queue wiith single empty After insertion, queue becomes full Back 1 76 MAX_QUEUE -1 0 Front
35 Array-Based Queue Implementation 2. Circular Arrays Implementation That is why we need a count If count ==MAX_QUEUE Queue is FULL Else if count ==0 Queue is EMPTY
36 Array-Based Queue Implementation 2. Circular Array Implementation final int MAZ_QUEUE = maxinum-size-of-queue; Object [] items; Int front; Int back; int count; Back Front MAX_QUEUE -1
37 Array-Based Queue Implementation 2. Circular Arrays Implementation Initial condition: Count = 0, Front = 0, Back = MAX_QUEUE – 1 The Wrap-around effect is obtained by using modulo arithmetic (%-operator) Insertion Increment Back, using modulo arithmetic Insert item Increment Count back = ( back + 1 ) % MAX_QUEUE; items[back} = newItem; ++count;
38 Array-Based Queue Implementation 2. Circular Array Implementation Deletion Increment Front using modulo arithmetic Decrement Count front = ( front + 1 ) % MAX_QUEUE; - - count;
39 Array-Based Queue Implementation public class ArrayQueue implements QueueInterface { private final int MAX_QUEUE = 50; // maximum size of queue private Object[ ] items; private int front, back, count; public ArrayQueue() { items = new Object[MAX_QUEUE]; front = 0; back = MAX_QUEUE-1; count = 0; } // end default constructor // queue operations: public boolean isEmpty() { return count == 0; } // end isEmpty public boolean isFull() { return count == MAX_QUEUE; } // end isFull
40 Array-Based Queue Implementation (2) public void enqueue(Object newItem) { if (!isFull()) { back = (back+1) % (MAX_QUEUE); items[back] = newItem; ++count; } else throw new QueueException("QueueException on enqueue: "+ "Queue full"); } // end enqueue public Object dequeue() throws QueueException { if (!isEmpty()) { // queue is not empty; remove front Object queueFront = items[front]; front = (front+1) % (MAX_QUEUE); --count; return queueFront; } else throw new QueueException("QueueException on dequeue: "+ "Queue empty"); } // end dequeue
41 Array-Based Queue Implementation (3) public void dequeueAll() { items = new Object[MAX_QUEUE]; front = 0; back = MAX_QUEUE-1; count = 0; } // end dequeueAll public Object peek() throws QueueException { if (!isEmpty()) { // queue is not empty; retrieve front return items[front]; } else { throw new QueueException("Queue exception on peek: " + "Queue empty"); } // end if } // end peek } // end ArrayQueue
42 Array Based Queue Test public class ArrayQueueTest { public static void main(String[] args) { ArrayQueue aQueue = new ArrayQueue(); System.out.println("Enqueuing:"); for (int i = 0; i < 9; i++) { System.out.print(" "+i); aQueue.enqueue(new Integer(i)); } // end for System.out.println("\nDequeuing:"); for (int i = 0; i < 9; i++) { System.out.print(" "+aQueue.dequeue()); } // end for System.out.println(); } // end main } // QueueTest
43 Full/Empty Determination without Counters Disadvantage of Using a counter Overhead of maintaining a counter or flag Using a flag isFull Flag is set to true when it is full Flag is set to false when the queue is not full Expense as using the counter
44 Full/Empty Determination without Counters Queue size counters will not be used Use extra array location Declare MAX_QUEUE +1 locations, but only use MAX_QUEUE of them for queue items Full/Empty determinations will be made using the relative positions of front and back. back will be initialized to –-1 and front to 0 as before. Both front and back will be incremented with wraparound.
45 Array-Based Queue Implementation 2. Circular Array Implementation Full QueueEmpty Queue Back Front MAX_QUEUE Front & Back MAX_QUEUE
46 Final Method for Full/Empty Determination without Counters To allow different tests for empty and full Sacrifice one array slot so that a full Queue uses all but one array slot Thus the test for a full Queue becomes: (back + 1) % (MAX_QUEUE+1) == front While the test for an empty Queue remains: back== front If the elements of the queue are complex data structure, the memory wasted may be significant
47 ADT List Queue Implementation Use ADT List to implement the queue Pre- & Post-conditions are the same as before The implementation is much simpler
48 ADT List Queue Implementation Front is the position 1 of the list Back is the item at the end of the list
49 ADT List Queue Implementation Dequeue () List.remove(1); Peek() List.get(1); Enqueue (newItem) List.add(list.size()+1, newitem);
50 ListQueue Implementation public class ListQueue implements QueueInterface { private ListInterface list; public ListQueue() { list = new ListReferenceBased (); } // end default constructor // queue operations: public boolean isEmpty() { return list.isEmpty(); } // end isEmpty public void dequeueAll() { list.removeAll(); } // end dequeueAll
51 ListQueue Implementation (2) public void enqueue(Object newItem) { list.add(list.size()+1, newItem); } } // end enqueue
52 ListQueue Implementation (3) public Object dequeue() throws QueueException { if (!isEmpty()) { // queue is not empty; remove front Object queueFront = list.get(1); list.remove(); return queueFront; } else { throw new QueueException("QueueException on dequeue:" + "queue empty"); } // end if } // end dequeue
53 ListQueue Implementation (4) public Object peek() throws QueueException { if (!isEmpty()) { return flist.get(1); } else { throw new QueueException("QueueException on peek:" + "queue empty"); } // end if } // end peek } // end ListQueue
54 ADT Queue Implementation Comparison Reference-Based More complicated than ADT List Most flexible No size restrictions Array-Based No overhead of pointer manipulation Prevents adding elements if the array is full ADT List-Based Simpler to write Not as efficient as using a linked list directly