Bird
0
0
DSA Cprogramming

Implement Stack Using Queue in DSA C

Choose your learning style9 modes available
Mental Model
A stack works like a pile where the last item added is the first removed. A queue works like a line where the first item added is the first removed. We can use a queue to mimic a stack by rearranging the order after each addition.
Analogy: Imagine a line of people (queue) but you want to always serve the last person who joined first (stack). After each new person joins, you make them go to the front of the line by moving everyone else behind them.
Queue: front -> [1] -> [2] -> [3] -> rear
Stack: top -> [3] -> [2] -> [1] -> bottom
Dry Run Walkthrough
Input: Push 1, Push 2, Push 3, Pop
Goal: Use a queue to behave like a stack and pop the last pushed element
Step 1: Push 1 into queue
front -> [1] -> rear
Why: Add first element normally
Step 2: Push 2 into queue, then rotate queue to move 2 to front
front -> [2] -> [1] -> rear
Why: Rotate so last pushed is at front to simulate stack top
Step 3: Push 3 into queue, then rotate queue to move 3 to front
front -> [3] -> [2] -> [1] -> rear
Why: Rotate again to keep last pushed element at front
Step 4: Pop from queue (remove front)
front -> [2] -> [1] -> rear
Why: Pop removes the last pushed element, simulating stack pop
Result:
front -> [2] -> [1] -> rear
Pop returned 3
Annotated Code
DSA C
#include <stdio.h>
#include <stdlib.h>

#define MAX 100

typedef struct {
    int data[MAX];
    int front;
    int rear;
    int size;
} Queue;

void initQueue(Queue* q) {
    q->front = 0;
    q->rear = -1;
    q->size = 0;
}

int isEmpty(Queue* q) {
    return q->size == 0;
}

int isFull(Queue* q) {
    return q->size == MAX;
}

void enqueue(Queue* q, int val) {
    if (isFull(q)) return;
    q->rear = (q->rear + 1) % MAX;
    q->data[q->rear] = val;
    q->size++;
}

int dequeue(Queue* q) {
    if (isEmpty(q)) return -1;
    int val = q->data[q->front];
    q->front = (q->front + 1) % MAX;
    q->size--;
    return val;
}

int queueSize(Queue* q) {
    return q->size;
}

// Stack implemented using one queue
typedef struct {
    Queue q;
} StackUsingQueue;

void initStack(StackUsingQueue* s) {
    initQueue(&s->q);
}

void push(StackUsingQueue* s, int val) {
    enqueue(&s->q, val); // add new element
    int sz = queueSize(&s->q);
    // rotate queue to move new element to front
    for (int i = 0; i < sz - 1; i++) {
        int temp = dequeue(&s->q); // remove front
        enqueue(&s->q, temp);      // add it to rear
    }
}

int pop(StackUsingQueue* s) {
    if (isEmpty(&s->q)) return -1;
    return dequeue(&s->q); // front is top of stack
}

int main() {
    StackUsingQueue s;
    initStack(&s);

    push(&s, 1);
    push(&s, 2);
    push(&s, 3);

    int val = pop(&s);
    printf("Popped: %d\n", val);

    // Print remaining stack elements
    printf("Stack after pop: ");
    while (!isEmpty(&s.q)) {
        printf("%d ", dequeue(&s.q));
    }
    printf("\n");

    return 0;
}
enqueue(&s->q, val); // add new element
Add new element to queue rear
for (int i = 0; i < sz - 1; i++) { int temp = dequeue(&s->q); enqueue(&s->q, temp); }
Rotate queue to move last pushed element to front
return dequeue(&s->q); // front is top of stack
Pop removes front element which is stack top
OutputSuccess
Popped: 3 Stack after pop: 2 1
Complexity Analysis
Time: O(n) for push because we rotate all elements to keep last pushed at front; O(1) for pop as it just dequeues front
Space: O(n) for storing n elements in the queue
vs Alternative: Naive approach using two queues can have O(1) push but O(n) pop; this approach optimizes pop to O(1) at cost of O(n) push
Edge Cases
Pop from empty stack
Returns -1 indicating stack is empty
DSA C
if (isEmpty(&s->q)) return -1;
Push into full queue
Push is ignored as queue is full, no overflow handling
DSA C
if (isFull(q)) return;
When to Use This Pattern
When you need stack behavior but only have a queue, use this pattern to reorder elements after each push so pop is efficient.
Common Mistakes
Mistake: Not rotating the queue after push, so pop returns oldest element instead of last pushed
Fix: Rotate the queue by dequeuing and enqueuing all elements except the last pushed after each push
Mistake: Trying to pop from empty queue without checking, causing errors
Fix: Check if queue is empty before dequeueing in pop
Summary
Implements a stack using a single queue by rotating elements after each push.
Use when only queue data structure is available but stack operations are needed.
The key is to rotate the queue after each push so the last pushed element is always at the front.