# 1 Queues (Continued) Applications for a queue Linked queue implementation Array queue implementation Circular array queue implementation Reading L&C 3.

## Presentation on theme: "1 Queues (Continued) Applications for a queue Linked queue implementation Array queue implementation Circular array queue implementation Reading L&C 3."— Presentation transcript:

1 Queues (Continued) Applications for a queue Linked queue implementation Array queue implementation Circular array queue implementation Reading L&C 3 rd : 5.2-5.5, 8.3 2 nd : 7.1-7.8

2 Applications for a Queue A queue can be used as an underlying mechanism for many common applications –Simulation of client-server operations –Radix Sort –Scheduling processes in an operating system such as printer queues

3 Cycling through Code Keys The Caesar cipher is simple letter shifting Each letter is treated as its number 0-25 in the alphabet and each letter is encoded as: cipher value = (letter value + constant) % 26 The message is decoded letter by letter: letter value = (cipher value – constant) % 26 if (letter value < 0) letter value += 26 Using the constant 7, the word “queue” would be coded as “xblbl” Note: the word’s “pattern” is recognizable

4 Cycling through Code Keys The Caesar cipher is easy to solve because there are only 26 possible “keys” to try It can be made harder by cycling through a key set of values such as 3, 1, 7, 4, 2, 5 We put that sequence of numbers in a queue As we encode each letter, we dequeue a number for the constant and re-enqueue it - cycling through the entire key set as many times as needed for the message length

5 Cycling through Code Keys Using that queue of numbers as the constant values, the word “queue” becomes “tvlyg” Note: the word’s “pattern” is not recognizable If we are encoding a message containing the entire Unicode character set, we can omit the modulo 26 operator as in the text book code See L&C, Listing 5.2

6 Ticket Counter Simulation See L&C Listing 5.3 and 5.4 The simulation in this example sets up the queue with customers arriving at regular 15 second intervals This is not the most meaningful analysis because it doesn’t take into account the typical variations in arrival rate One customer every 15 seconds could mean 8 customers arriving at one time and then 2 minutes with no arriving customers

7 Linked Queue Implementation We can use the same LinearNode class that we used for LinkedStack implementation We use attribute names “front” and “rear” to have a meaning consistent with a queue Object of type T front LinearNode next; T element; Object of type T LinearNode next; T element; null count integer Object of type T LinearNode next; T element; rear

8 Linked Queue Implementation enqueue – O(1) public void enqueue (T element) { LinearNode node = new LinearNode (element); if (isEmpty()) front = node; else rear.setNext(node); rear = node; count++; } Note the difference between the enqueue method and the Stack push method

9 Linked Queue Implementation dequeue – O(1) public T dequeue () throws EmptyStackException { if (isEmpty()) throw new EmptyStackException(); T result = front.getElement(); front = front.getNext(); count--; if (isEmpty()) rear = null; return result; } Note the difference between the dequeue method and the stack pop method

10 Array Queue Implementation We can use an array of elements as a queue The front is implicitly index 0 and rear is the index of next available element in the array Object of type T null T [ ] queue rear Object of type T

11 Array Queue Implementation enqueue – O(1) public void enqueue (T element) { if (size() == queue.length) expandCapacity(); stack [rear++] = element; } expandCapacity is similar to private helper method used in ArraySet and Stack classes

12 Array Queue Implementation dequeue() – O(n) public T dequeue() throws EmptyStackException { if (isEmpty()) throw new EmptyStackException(); T result = queue[0]; rear--; for (int scan = 0; scan < rear; scan++) queue[scan] = queue[scan + 1]; queue[rear] = null; return result; }

13 Array Queue Implementation Notice that the dequeue is O(n) due to the shifting of the elements in the array queue after the 0 th element has been copied out This introduces a potential performance problem that we would like to avoid Using the 0 th element of the array as the rear of the queue doesn’t solve the problem – just moves it to the enqueue operation With a better design, we can avoid it

14 Circular Array Queue Implementation This design eliminates the shifting of the elements as part of the dequeue operation Commonly called circular queue We keep an integer for both the front and rear of the queue in the array and never shift the elements in the array When we increment either front or rear to the length of the array, we do not expand the capacity. We set them back to zero to reuse the lower elements in the array

15 Circular Array Queue Implementation 0 1 2 N-2 N-1 3 4 5 6 front3 rear7 count4 7

16 Circular Array Queue Implementation 0 1 2 N-2 N-1 3 4 5 6 front 2rear N-2 count4 7

17 Circular Array Queue Implementation Method enqueue can not use: rear++; Method dequeue can not use: front++; To increment rear, enqueue must use: rear = (rear + 1) % queue.length; To increment front, dequeue must use: front = (front + 1) % queue.length;

18 Circular Array Queue Implementation When the front catches up to the rear (a snake eating its own tail?), our code must expand the capacity of the array (replacing the original array with a larger one) When our code expands the capacity, it must cycle through the original array from front index to rear index value as it copies from the smaller array to the larger array Then, it sets new values for front and rear