Queues
Queues
Queue
1
Introduction to Queues
● Well that was all about LIFO order, we all know that most lines( or QUEUES) follow the
FIFO order. Don’t they?
And just as we expected, the output is all the tasks being printed in the FIFO order.
Introduction to Queues
● In Java, you can use an inbuilt Queue implemented using a Linked List.
● Here, the convention changes a bit - Java queues don't have enqueue and dequeue
methods, these operations are carried out using the following methods:
● So, if a customer is making a request for 4 tickets, but there are only three
tickets in the system, this request would have to be denied.
● Thus, each time a request is made, the tickets available are checked. If the
tickets are available, then the request is dequeued and the next request in
the queue is processed.
Implementation of Queue
ID:
570834163
Implementation of Queue
public T remove() {
return this.list.remove(); }
● Well, now you’ve learnt the basics of both stacks and queues. Here’s a challenging
task for you.
● But, before let’s revise the difference between them once again.
Implementation of Stack using Queues
● Stacks are the data structure that follows LIFO property. Stack has a restriction that
insertion and deletion can be done only at one end which is known as the 'TOP' of
the stack.
Implementation of Stack using Queues
● On the other hand, Queues are the data structure that follows FIFO property.
● In queues, you can insert (enqueue) elements only at one end which is known as
‘TAIL’ and deletion (dequeue) of elements in the queue can take place at the other
end which is known as ‘HEAD’.
Implementation of Stack using Queues
● The major difference therefore is that if the elements are inserted at the same end
in both these data structures, they removal takes place at different end or vice-
versa.
● We can therefore conclude that either the PUSH operation will be same as
ENQUEUE or the POP operation will be same as DEQUEUE in our stack
implemented with queues.
● The former case is called implementing stack making POP operation costly and
the latter is called, as you would have guessed already, implementing stack making
PUSH operation costly.
Implementation of Stack using Queues
● The Q1 will be acting as our stack, i.e PUSH and POP operations will insert and
remove elements from the head of Q1.
● As told already, this implementation involves assuming the heads of both stack
and queue as same. (PUSH = ENQUEUE)
● Therefore, the ENQUEUE operation does the same task as the PUSH operation and
add elements to the head of Q1. Q2 is not used in PUSH.
Implementation of Stack using Queues
PUSH 1: 1 is enqueued to Q1. The head of the Q1 becomes the head of the stack.
1
○ The POP operation will be performed using both queues Q1 and Q2.
○ All the elements except the last one( the element to be popped) will be
dequeued one by one from Q1 and enqueued into the Q2.
○ The remaining element from Q1 is dequeued and returned after the names of
Q1 and Q2 are swapped.
● Let’s perform the pop operation on this stack from our last slide:
Front of Rear of Queue
We have pushed
from this side
Queue 3 5 1 (Dequeue)
(Enqueu
(head of the
e)
stack)
Implementation of Stack using Queues
Q1:3 5 1 Q2:
STEP 1: Dequeue all the elements except last from Q1 and enqueue them to Q2.
Q1:3 5 1 Q2:
Q1:3 5 1 Q2:
● What will be the output after the following commands are executed?
○ PUSH(1)
○ PUSH(2)
○ PUSH(3)
○ POP
Let’s quickly check the algorithm if we implement the stack making PUSH
operation costly:
● The POP operation in this case will simply be a dequeue from our queue Q1.
○ Dequeue all the elements from Q1 one by one and enqueue them to Q2.
● To implement a stack using a single queue, we basically need to solve the purpose
of the other queue we used to implement the stack using two queues.
● We assigned either ENQUEUE or DEQUEUE operation as PUSH or POP and used the
second queue to implement the remaining function.
● This was because if the elements in both queue and stack are added/ removed
from same end, they are removed/added to different ends.
Implementation of Stack using Queues
● So our new objective is to manipulate our queue such that if the element is added
at one end, it reaches the opposite end before the next operation. Let’s see our
new PUSH and POP functions now:
● PUSH(x)
● POP
● Assume that our queue already has elements 1, 2, 3 in it and now we want want to
PUSH 4 into our stack.
● Step 1 will be to calculate the size of the stack/queue which will be equal to 3 here.
● Now we dequeue from the queue and enqueue the element i.e. 1 back to the
queue. The queue now becomes 2, 3, 4, 1.
● We repeat the same step 3(size) times. Finally the queue becomes 4, 1, 2, 3.
Implementation of Stack using Queues
The following illustration will help you understand the concept better:
Enqueue 4 Dequeue 1
3 2 1 4 3 2 1 1 4 3 2
Enqueue 1
Dequeue 2 Enqueue 2
Dequeue 3
3 2 1 4 2 1 4 3
Enqueue 3
Implementation of Stack using Queues
int pop(){
if (q.isEmpty()) {
System.out.println("Stack is empty");
System.exit(0); }
int x = q.remove();
return x;
}
Identify a Palindromic String
● Well here’s another problem and it’s a problem you already are familiar with.
● Just to revise, a palindrome is a word, string, phrase or sentence that reads same
backward as forward. For example, “MALAYALAM”, “LEVEL” etc.
● As queues and stacks are one of the most frequently used data structures for
storing and modifying information, we need to devise an algorithm to check
whether the characters of the input string forms a palindrome or not using either
stacks or queues.
Identify a Palindromic String
Let’s see the steps of the algorithm to help us check the palindromic nature of a stack.
1. Use a ‘for’ loop to push each character of the string into an array stack.
3. pop() the characters from the stack one by one and add it to the reversedString.
4. Compare the input string and the reversed string. If they are equal, then print
“The input String is a palindrome”.
5. If they are not equal, then print “The input String is not a palindrome”.
Identify a Palindromic String
● The space complexity of the discussed approach is O(n2) due to the variable string
used.
● Strings are immutable in Java; therefore, a new string of length ‘n’ will be created
‘n’ times.
● To avoid creating a new string everytime you add a character, you can use
StringBuilder class in Java.
● The strings created using StringBuilder class are modifiable and do not need any
repetitive creation.
● Therefore, the space complexity is reduced to O(n).
Duplicate Parentheses Problem
● You all remember the “Matching Parentheses” problem from Stacks. Don’t you?
● If you had to solve this problem manually, wou will definitely start by resolving the
innermost parentheses. Our algorithm works on the same principle.
● We start by declaring a stack and iterating through the complete length of string
and pushing the elements inside the stack until we encounter the first closing
parentheses “)”.
Duplicate Parentheses Problem
● Now we start popping the elements till we encounter the first “(”.
● Otherwise, after full string traversal, we say that it does not contains duplicate
parentheses.
Duplicate Parentheses Problem
Let’s see the java code:
In the coming few slides, we will be shortly discussing a few problem statements on
stacks and queues, which will be followed by the approach to solve the question. These
questions are:
● Reverse a stack
● But what if we want the input sequence to be reversed within the stack itself?
● For example: If the input stack contains elements { a b c d e } where 'e' is the
element at the top of the stack then reverse stack would contain elements { e d c b
a } where 'a' is the element at the top of the stack.
Reverse A Stack
Let’s approach this problem with the pseudocode given below which uses two functions
in its implementation:
● The next problem is about finding the kth largest element given a set of elements.
● To find the kth largest element, you will have to somehow compare every element
with every other element. Here, the task is to first sort and then find the kth
largest element in the given input sequence.
3. Return ‘temp’ stack, which contains all the elements in the input stack in descending
sorted order.
Maximum of Subarrays of Size K
Let’s see the steps of the algorithm to help us find the maximum element in each sub
group:
● To create sub groups of size ‘K’, you need to create a nested ‘for’ loop.
● The outer loop will begin to roll from 0 to n-K, and the inner ‘for’ loop will execute
1,2,3. . . . up to ‘K’ times. Each time an outer loop is invoked, the inner loop
executes ‘K’ times.
● The outer loop initializes the first element of the subgroup as ‘max’ and the inner
loop will compare it with all the elements in that particular
● sub group.
● If any number is greater than the ‘max’, then the smaller one will be replaced
● by it.
Maximum of Subarrays of Size K
I hope you have guessed it right. It will be O(n*K) where n is the size of the
array and K is the size of each sub group. This complexity is not efficient.
● If you observe the previous algorithm carefully, you will notice that you are
making redundant comparisons. You can avoid the redundant comparisons by
using another data structure to store the maximum number in the last subgroup.
● For this purpose, you can use a data structure called a Deque, instead of using
Stacks and Queues, to save memory, because Stacks and Queues provide access
to the elements from one side only, i.e., either the head or the tail, whereas you
can use a Deque to insert/delete/peek elements from either side.
Maximum of Subarrays of Size K
● So, when you add ‘maximum’ values from the current subgroup, you can also,
simultaneously, remove the ‘maximum’ values of the previous subgroups that
are not a part of the current subgroup.
● Now, think and create an algorithm that would give you the best possible
solution to the problem and would have time complexity of the order of O(n)
and space complexity of O(K).
Implementation of Queue using Stack
We have already seen the implementation of Stack using Queue. Now let’s see how to
implement a Queue using Stack. In this approach, we will use one Stack and recursion
which will internally use the call stack.
● The dequeue operation pops all elements from the stack using recursion and stores
them in the call stack.
● When the stack is left with a single item, it pops that item, prints it and returns back.
● Finally, it pushes all elements back into the stack from the call stack as the recursion
unfolds.
Implementation of Queue using Stack
● enQueue():
1. Push the element to the Stack.
● deQueue():
1. Pop all the elements from the Stack recursively until Stack item count is
equal to 1.
2. If Stack item count = 1, Pop item from Stack, Print it & Return.
3. Push all popped element back to Stack.
Implementation of Queue using Stack