Implement Queue using Stacks

A queue can be implemented using two stacks. Let queue to be implemented be q and stacks used to implement q be stack1 and stack2. q can be implemented in two ways:

Method 1 (By making enQueue operation costly)
This method makes sure that newly entered element is always at the top of stack 1, so that deQueue operation just pops from stack1. To put the element at top of stack1, stack2 is used.

enQueue(q, x)
  1) While stack1 is not empty, push everything from satck1 to stack2.
  2) Push x to stack1 (assuming size of stacks is unlimited).
  3) Push everything back to stack1.

dnQueue(q)
  1) If stack1 is empty then error
  2) Pop an item from stack1 and return it

Method 2 (By making deQueue operation costly)
In this method, in en-queue operation, the new element is entered at the top of stack1. In de-queue operation, if stack2 is empty then all the elements are moved to stack2 and finally top of stack2 is returned.

enQueue(q,  x)
  1) Push x to stack1 (assuming size of stacks is unlimited).

deQueue(q)
  1) If both stacks are empty then error.
  2) If stack2 is empty
       While stack1 is not empty, push everything from satck1 to stack2.
  3) Pop the element from stack2 and return it.

Method 2 is definitely better than method 1. Method 1 moves all the elements twice in enQueue operation, while method 2 (in deQueue operation) moves the elements once and moves elements only if stack2 empty.

Implementation of method 2:

/* Program to implement a queue using two stacks */
#include<stdio.h>
#include<stdlib.h>

/* structure of a stack node */
struct sNode
{
   int data;
   struct sNode *next;
};
 
/* Function to push an item to stack*/
void push(struct sNode** top_ref, int new_data);
 
/* Function to pop an item from stack*/
int pop(struct sNode** top_ref);
 
/* structure of queue having two stacks */
struct queue
{
   struct sNode *stack1;
   struct sNode *stack2;
};
 
/* Function to enqueue an item to queue */
void enQueue(struct queue *q, int x)
{
   push(&q->stack1, x);
}
 
/* Function to dequeue an item from queue */
int deQueue(struct queue *q)
{
   int x; 
 
   /* If both stacks are empty then error */
   if(q->stack1 == NULL && q->stack2 == NULL)
   {
      printf("Q is empty");
      getchar();
      exit(0);
   }

   /* Move elements from satck1 to stack 2 only if 
       stack2 is empty */
   if(q->stack2 == NULL)
   {
     while(q->stack1 != NULL)
     {
        x = pop(&q->stack1);
        push(&q->stack2, x);
     }
   } 

   x = pop(&q->stack2);
   return x;
}
 
/* Function to push an item to stack*/
void push(struct sNode** top_ref, int new_data)
{
  /* allocate node */
  struct sNode* new_node =
            (struct sNode*) malloc(sizeof(struct sNode));
 
  if(new_node == NULL)
  {
     printf("Stack overflow \n");
     getchar();
     exit(0);
  }            
 
  /* put in the data  */
  new_node->data  = new_data;
 
  /* link the old list off the new node */
  new_node->next = (*top_ref);   
 
  /* move the head to point to the new node */
  (*top_ref)    = new_node;
}
 
/* Function to pop an item from stack*/
int pop(struct sNode** top_ref)
{
  int res;
  struct sNode *top;
 
  /*If stack is empty then error */
  if(*top_ref == NULL)
  {
     printf("Stack overflow \n");
     getchar();
     exit(0);
  }
  else
  {
     top = *top_ref;
     res = top->data;
     *top_ref = top->next;
     free(top);
     return res;
  }
}
 
/* Driver function to test anove functions */
int main()
{
   /* Create a queue with items 1 2 3*/
   struct queue *q = (struct queue*)malloc(sizeof(struct queue));
   q->stack1 = NULL;
   q->stack2 = NULL;
   enQueue(q, 1);
   enQueue(q, 2);
   enQueue(q, 3);    
 
   /* Dequeue items */
   printf("%d  ", deQueue(q));
   printf("%d  ", deQueue(q));
   printf("%d  ", deQueue(q));  
 
   getchar();
}

Queue can also be implemented using one user stack and one Function Call Stack.
Below is modified Method 2 where recursion (or Function Call Stack) is used to implement queue using only one user defined stack.

enQueue(x)
  1) Push x to stack1.

deQueue:
  1) If stack1 is empty then error.
  2) If stack1 has only one element then return it.
  3) Recursively pop everything from the stack1, store the popped item 
    in a variable res,  push the res back to stack1 and return res

The step 3 makes sure that the last popped item is always returned and since the recursion stops when there is only one item in stack1 (step 2), we get the last element of stack1 in dequeue() and all other items are pushed back in step 3.

Implementation of method 2 using Function Call Stack:

/* Program to implement a queue using one user defined stack and one Function Call Stack */
#include<stdio.h>
#include<stdlib.h>
 
/* structure of a stack node */
struct sNode
{
   int data;
   struct sNode *next;
};
 
/* structure of queue having two stacks */
struct queue
{
  struct sNode *stack1;
};
 
/* Function to push an item to stack*/
void push(struct sNode** top_ref, int new_data);
 
/* Function to pop an item from stack*/
int pop(struct sNode** top_ref);
 
/* Function to enqueue an item to queue */
void enQueue(struct queue *q, int x)
{
  push(&q->stack1, x);
}
 
/* Function to dequeue an item from queue */
int deQueue(struct queue *q)
{
   int x, res; 
 
   /* If both stacks are empty then error */
   if(q->stack1 == NULL)
   {
     printf("Q is empty");
     getchar();
     exit(0);
   }
   else if(q->stack1->next == NULL)
   {
      return pop(&q->stack1);
   }
   else
   {
      /* pop an item from the stack1 */
      x = pop(&q->stack1);
 
      /* store the last dequeued item */
      res = deQueue(q);
 
      /* push everything back to stack1 */
      push(&q->stack1, x);
 
      return res;
   }
}
 
/* Function to push an item to stack*/
void push(struct sNode** top_ref, int new_data)
{
  /* allocate node */
  struct sNode* new_node =
            (struct sNode*) malloc(sizeof(struct sNode));
 
  if(new_node == NULL)
  {
     printf("Stack overflow \n");
     getchar();
     exit(0);
  }           
 
  /* put in the data  */
  new_node->data  = new_data;
 
  /* link the old list off the new node */
  new_node->next = (*top_ref);  
 
  /* move the head to point to the new node */
  (*top_ref)    = new_node;
}
 
/* Function to pop an item from stack*/
int pop(struct sNode** top_ref)
{
  int res;
  struct sNode *top;
 
  /*If stack is empty then error */
  if(*top_ref == NULL)
  {
     printf("Stack overflow \n");
     getchar();
     exit(0);
  }
  else
  {
     top = *top_ref;
     res = top->data;
     *top_ref = top->next;
     free(top);
     return res;
  }
} 
 
/* Driver function to test above functions */
int main()
{
  /* Create a queue with items 1 2 3*/
  struct queue *q = (struct queue*)malloc(sizeof(struct queue));
  q->stack1 = NULL;
 
  enQueue(q, 1);
  enQueue(q, 2);
  enQueue(q, 3);    
 
  /* Dequeue items */
  printf("%d  ", deQueue(q));
  printf("%d  ", deQueue(q));
  printf("%d  ", deQueue(q));  
 
  getchar();
}



Please write comments if you find any of the above codes/algorithms incorrect, or find better ways to solve the same problem.





  • gaurav_sharma_17

    /*
    Queue can also be implemented using one user stack and one Function Call Stack.
    Below
    is modified Method 2 where recursion (or Function Call Stack) is used
    to implement queue using only one user defined stack.

    enQueue(x)
    1) Push x to stack1.

    deQueue:
    1) If stack1 is empty then error.
    2) If stack1 has only one element then return it.
    3) Recursively pop everything from the stack1, store the popped item

    in a variable res, push the res back to stack1 and return res

    The
    step 3 makes sure that the last popped item is always returned and
    since the recursion stops when there is only one item in stack1 (step
    2), we get the last element of stack1 in dequeue() and all other items
    are pushed back in step 3.

    */

    #include
    #include
    #include
    #include
    #include
    #include

    class Q
    {
    public :

    void enQueue(std::stack&s1, int x)
    {
    s1.push(x);
    }

    int deQueue(std::stack &d)
    {
    int x, res;
    if(d.empty())

    {
    printf(“Q is empty”);
    getchar();
    exit(0);
    }
    else if(d.size() == 1)
    {
    x=d.top();
    d.pop();

    return x;
    }
    else
    {
    /* pop an item from the stack1 */
    x=d.top();
    d.pop();

    /* store the last dequeued item */

    res = deQueue(d);

    /* push everything back to stack1 */
    d.push(x);
    return res;
    }
    }
    };

    int main()
    {

    std::stack s1;
    Q d;
    d.enQueue(s1,7);
    d.enQueue(s1,71);
    d.enQueue(s1,17);
    d.enQueue(s1,47);
    d.enQueue(s1,74);
    d.enQueue(s1,741);
    cout<<d.deQueue(s1);
    cout<<endl<<"rest of the queue :n";
    while (!s1.empty())
    {
    std::cout<<' '<< s1.top();
    s1.pop();
    }
    getchar();
    }

  • Chad

    How would you implement a copy constructor for Queue?

  • Aditya

    What is the practical use case for such a problem? (obviously except that there are only stacks available and no queues)

  • Piyush

    My method.

    In this approach, enqueue operation is o(1) and dequeue is avg o(2).

    #include
    #include

    #define ERROR 0xFFFFFFFF
    using namespace std;

    template
    class Queue {
    private:
    stack A,B;
    public:
    int enqueue(T element)
    {
    A.push(element);
    return 1;
    }
    int dequeue(T *element)
    {
    if(B.empty())
    {
    if(A.empty())
    {
    *element = ERROR;
    return -1;
    }
    while(!A.empty())
    {
    B.push(A.top());
    A.pop();
    }
    }
    *element = B.top();
    B.pop();
    return 1;
    }
    void traverse()
    {
    while(!B.empty())
    {
    cout << " " <<B.top();
    B.pop();
    }
    while(!A.empty())
    {
    B.push(A.top());
    A.pop();
    }
    while(!B.empty())
    {
    cout << " " <<B.top();
    B.pop();
    }
    }
    };

    int main()
    {
    int ptr;
    Queue q;
    q.enqueue(5);
    q.enqueue(10);
    q.enqueue(15);
    q.enqueue(20);
    q.dequeue(&ptr);
    q.dequeue(&ptr);
    q.enqueue(25);
    q.enqueue(30);
    q.enqueue(35);
    q.enqueue(40);
    q.dequeue(&ptr);
    q.dequeue(&ptr);
    q.enqueue(45);
    q.enqueue(50);
    q.dequeue(&ptr);
    q.traverse();
    return 0;
    }

    • Piyush

      Damn !! The newer interface of geeksforgeeks is not beautifying the code properly. It messed my code.

      Please consider the code till dequeue only. Imagine that the class ended after that.

      I tried to write traverse func, but it got messed up here with main().

  • rengasami21

    In method 2 (using two stacks), don’t we need to push all the elements back from stack 2 to stack 1? Because when we pop out for deque stack 1 becomes empty.

    Am I missing something? Can somebody help me?

    • Abhishek Choudhery

      No, the next element that you would want on the next pop operation is now at the top of Stack 2. See the Algo for Pop again!
      Even I had the same doubt previously

  • rengasami21

    Hi,

    As per method 2 of using 2 stacks, we are popping every element of stack 1 and pushing it to stack 2 when we dequeue. So after this step, the stack 1 is empty. Now we are enqueuing an element, it will get added to stack 1. Now if we would like to dequeue an element, that one element will be popped out and pushed to stack 2, now if I pop from stack 2, it will give me only the element that was enqueued just now.

    Don’t we need to push all the elements from Stack 2 to Stack 1 after dequeue?

    Am I missing something here? Can somebody help me?

    regards,
    Rengasami R

    • yyk

      yah…you r missing…point that….
      “While dequeuing, when there are no elements in stack 2 u r pushing all elements in stack 1 to stack 2 not everytime,,,,,,when there are elements in stack 2, u dequeue directly from stack 2….without pushing elements from stack 1″

  • spheroid
     
    #include<iostream>
    #include<stack>
    using namespace std;
    int main()
    {
    	stack<int> s,p,temp;
    	int opt;
    	int size;
    	int element;
    	do
    	{
    
    		cout<<" Enter 1 for Push \n Enter 2 for Pop \n Enter 3 to exit : ";
    		cin>>opt;
    		switch(opt)
    		{
    		case 1:
    			
    			cout<<" Enter Element :"<<endl;
    			cin>>element;
    			s.push(element);
    			break;
    
    		case 2:
    		
    		
    			size=s.size();
    			
    			while(size>1)
    			{
    				 p.push(s.top());
    				 s.pop();
    				 size--;
    			}
    			if(s.size()==0)
    			{
    				cout<<" Element cant be Popped Out \n";
    			}
    			
    			else
    			{
    			cout<<" Popped element is :"<<s.top()<<endl;
    			s.pop();
    			while(!p.empty())
    			{
    				 s.push(p.top());
    				 p.pop();
    				 
    			}
    			}
    			break;
    
    		default:
    			cout<<" Enter Valid Option \n";
    
    
    		}
    	}while(opt!=3);
    
    
    	   getchar();
    }
    
     
  • BackBencher

    @all:
    If we make stack using link-list then there is need to check the overflow condition in PUSH function. I think there is no limit on size of stack.Let me know if i am wrong.

    Thanks…

  • Palash

    One point that we all should note is that method one is amortized O(n), while method 2 is amortized O(1).

  • Joe Schulte

    I think you can optimize this by only moving data from one stack to the other when needed. If you are en-queuing first make sure all the data is on stack 1, then push the new item on the top of 1. If you are de-queuing first make sure that all the data is on stack 2 then pop the top item from stack 2. This method doesn’t make one operation faster than the other. It favors doing more than one push or pop at a time, worst case is no worst than the previously stated methods.

  • Ajinkya

    Method 2 idea, free of rascala pointers – Rajnikanth

     
    #include<stdio.h>
    #include<conio.h>
    #include<iostream.h>
    
    class stack
    {
       int *data; int size; int top;
       public:
       stack() { size=50; top=-1; data=new int[size]; }
       stack(int size) {this->size=50; top=-1; data=new int[size]; }
       int isempty() {if(top==-1) return 1; return 0; }
       void push(int x) { data[++top]=x; }
       int pop() { return(data[top--]); }
    };
    
    class Q
    {
          stack s1,s2;
          public:
          Q() {}
          void enqueue(int x) { s1.push(x); }
          int dequeue();
          int isempty() { if(s1.isempty() && s2.isempty()) return 1; return 0; }
    };
    
    int Q::dequeue()
    {
        if(s1.isempty() && s2.isempty()) {cout<<"\nUnderflow"; getch(); exit(0); }
        if(s2.isempty())
        {
           while(!s1.isempty())
              s2.push(s1.pop());
        }
        return(s2.pop());
    }
    
    int main()
    {
        Q q1;
        q1.enqueue(1);
        q1.enqueue(2);
        q1.enqueue(3);
        q1.enqueue(4);
        while(!q1.isempty())
           cout<<q1.dequeue()<<" ";
        cout<<q1.dequeue();
        getch();
        return 0;
    }
    
     
  • Ajinkya

    We have a right to live. Why should rascala pointers fuck our brains? So this is the same idea as method 2, without rascals (pointers)…
    -Rajnikant

     
    #include<stdio.h>
    #include<conio.h>
    #include<iostream.h>
    
    class stack
    {
       int *data; int size; int top;
       public:
       stack() { size=50; top=-1; data=new int[size]; }
       stack(int size) {this->size=50; top=-1; data=new int[size]; }
       int isempty() {if(top==-1) return 1; return 0; }
       void push(int x) { data[++top]=x; }
       int pop() { return(data[top--]); }
    };
    
    class Q
    {
          stack s1,s2;
          public:
          Q() {}
          void enqueue(int x) { s1.push(x); }
          int dequeue();
          int isempty() { if(s1.isempty() && s2.isempty()) return 1; return 0; }
    };
    
    int Q::dequeue()
    {
        if(s1.isempty() && s2.isempty()) {cout<<"\nUnderflow"; getch(); exit(0); }
        if(s2.isempty())
        {
           while(!s1.isempty())
              s2.push(s1.pop());
        }
        return(s2.pop());
    }
    
    int main()
    {
        Q q1;
        q1.enqueue(1);
        q1.enqueue(2);
        q1.enqueue(3);
        q1.enqueue(4);
        while(!q1.isempty())
           cout<<q1.dequeue()<<" ";
        cout<<q1.dequeue();
        getch();
        return 0;
    }
    
     
  • http://thekalinga.blogspot.com Ashok

    The method 2 is certainly not going to work properly if the scenario is like this

    PUSH A,B,C // Stack 1 (top to bottom)–>(C, B, A), STACK 2–>()
    POP // returns C ,Stack 1 (top to bottom)–>(), STACK 2–>(C, B)
    PUSH D // Stack 1 (top to bottom)–> (D), STACK 2–>(C, B)
    POP // returns D, Stack 1 (top to bottom)–> (), STACK 2–>(C, B)

    • GeeksforGeeks

      @Ashok: Please take a closer look at the algorithm. Your last POP step doesn’t seem to follow the algorithm. As per the algo, B will be returned in last step.

  • rahul

    plz tell in method 2 if i enqueue 123 den dequeue it willl dequeue 123 but suppose i called dequeue 2 times so stack 1 will have 123 and stack2 will have 3 and nw i enqueue in stack1 4 and then dequeue first 3 will be poped….but den dequeue called stack empty it will push 1234 in stack but 123 are of no use nw???plz xplain

    • WhatTheFuckAreYouSaying

      LYK DIS F YU CRY EVRYTYME

  • Water

    Awesome…. i was asked by this question in interview and this point cleared me many points.. thanks !!

    • Water

      this post* cleared many points

      • srinivas

        this is godd

         
        /* Paste your code here (You may delete these lines if not writing code) */
         
  • Sharat

    In the Dequeue function of Method2(Queue can also be implemented using one user stack and one Function Call Stack.) I sense there is a Bug.
    Step 3(copy paste from above algo): 3) Recursively pop everything from the stack1, store the last dequeued item and return it

    You don’t need to store the last de-queued element, as this condition will be met by step2. When you have popped all but the last element. Let me know if I missed something.

    Thanks,
    Sharat.

    • Sandeep

      @Sharat: Your point is valid. I have modified the algorithm and added few more words about step3. The program was correct, so no modifications in program.

      • mrn

        hi sandeep….
        i dint get why are u using pointer to pointer while passing control from enqueue/dequeue to push/pop functions. Can’t it be implemented using single pointer reference. Moreover at each point u are dereferencing the pointer to update its value which would not be the case if u wud have used single pointer to both functions push() and pop(). Tell me if i am wrong..

      • mrn

        @ sandeep
        i dint get why are u using pointer to pointer while passing control from enqueue/dequeue to push/pop functions. Can’t it be implemented using single pointer reference. Moreover at each point u are dereferencing the pointer to update its value which would not be the case if u wud have used single pointer to both functions push() and pop(). Tell me if i am wrong..

        • mrn

          sorry :)…
          i was out of my mind. Got the point . If we pass single pointer variable then a copy of that pointer is created in called function.The changes are done at dereferenced locations but pointers in the calling function are not updated. For this reason we need pointer to pointer.

  • windwaker

    Wow coooooooool