Ds Reportfinal
Ds Reportfinal
Team Members :
• Atharva Kulkarni: 202404309
• Pranav Mirkar: 202404307
• Pratik Kolhe: 202404319
The goal of this report is to demonstrate how a queue can be efficiently implemented using two stacks
and analyze its performance.
We’re going to explore an interesting way to implement a Queue using two Stacks. Sounds tricky? Let’s
break it down step by step.
What is Stack?
• A Stack is a linear data structure that follows a particular order in which the operations are
performed.
• Stack follows LIFO (Last in First Out)
• The stack follows the LIFO order, which means that the last element added to the stack will be
the first element to be removed.
Operations on stack
• push() - to insert an element into the stack. When you push an element onto the stack, you’re
adding it to the top.
• pop() - to remove an element from the stack. When you pop an element from the stack, you’re
removing it from the top.
What is Queue?
• A queue is a linear data structure that follows the First-In-First-Out (FIFO) principle.
• It operates like a line where elements are added at one end (rear) and removed from the other end
(front).
• FIFO principles the element added first will be removed first.
Operations on stack
Stack1 will be used to handle all enqueue operations. This means whenever we add an element, we
will always push it into stack1.
Stack2 will be used for dequeue operations. However, before removing elements from stack2, we
need to make sure that if stack2 is empty, all the elements from stack1 are moved to stack2. This
ensures that the oldest elements (those enqueued first) are on top of stack2, maintaining the FIFO
order.
Let’s break this down into steps for both enqueue and dequeue operations.
The enqueue operation is the easiest part of the algorithm. When a new element is added to the
queue, it is always pushed directly onto stack1. Since a stack follows LIFO (Last In, First Out), the
latest element will always stay at the top of stack1.
Step 2 - That's it! There’s no need for any additional operations for enqueueing.
The element stays in stack1 until it’s eventually dequeued by the dequeue() function.
O(1): Pushing an element into stack1 takes constant time, making this an efficient operation.
If stack2 is not empty, we simply pop the top element from stack2. Since stack2 holds elements
in the correct order for dequeuing (FIFO), we don’t need to do anything else.
If stack2 is empty, it means we don’t have any elements in the correct order for dequeuing. In
this case, we need to move all elements from stack1 to stack2:
While stack1 is not empty, pop the elements one by one from stack1 and push them onto stack2.
This reverses the order of the elements. Now, the oldest element that was first added to stack1
will be on top of stack2.
Once this transfer is complete, we can pop the top element from stack2. This element is now the
front of the queue (the one that was added first).
This approach demonstrates how a queue can be implemented using stacks, showing the
versatility of stacks.
The space complexity is O(n) for both stack1 and stack2, which is optimal and similar to using a
single queue directly.
• Simpler Code:
The code is relatively simple to implement once you understand the concept of transferring
elements between stacks.
While this approach is good for learning and problem-solving, it may not be used often in real-
world applications where a direct queue data structure is more appropriate and efficient.
• Extra Overhead:
There is an extra step of transferring elements between two stacks, which introduces additional
overhead. If a large number of dequeue operations are required, this approach becomes costly in
terms of performance.