Implement queue using stack

Implement queue using stack

In last post, we learned about stack data structure, in this post, we will discuss another data structure called queue. However, problem at hand is to implement queue using stack. Implement following functions on queue using stack
1. push() : inserts element at the back of queue.
2. pop() : removes element from front of the queue.
3. peek() : return element at front of the queue.
4. empty() : returns true if there is no element in queue.

Keep in mind that you can only use standard stack operations : push(), pop(), peek() and empty()

Stack is data structure where the element which is entered at top is taken out from top. It’s called LIFO pattern. Oppose to that queue is a FIFO data structure, where elements are entered at the rear and taken out from front. So effectively, we have to implement a FIFO data structure using LIFO data structure.

Implement queue using stack : Line of thoughts

To implement a FIFO using LIFO data structure, we need two stacks.

Push()
When element is inserted i.e push() operation, new element has to be pushed down the stack at bottom, as this should be the last element to be popped. So, to push an element in queue, we will take out all existing elements from stack s1 and put them into stack s2. Now, push the new element on to stack s1. At last, pop all elements from stack s2 back to stack s1. Below picture shows what happens when you we push 3 to queue and what happens behind the scene using stacks.

implement queue using stack

Complexity of push operation with this method is O(n). If there are n elements already inserted into queue, inserting a new element will require n pops from s1, n pushes to s2, then n pops from s2 and then again pushes to s1.

Pop()
If we follow the push operation described above, pop operation would be nothing but to return top of s1, which is constant operation with complexity of O(1).

Peek and empty functions also run always on stack s1. For peek, return s1.peek() and for empty return s1.empty()

Queue with stack : Push O(n), pop O(1) implementation

package com.company;

import java.util.Stack;

/**
 * Created by sangar on 23.9.18.
 */
public class QueueWithStack {
    private Stack<Integer> s1;
    private Stack<Integer> s2;

    public QueueWithStack(){
        s1 = new Stack<>();
        s2 = new Stack<>();
    }

    public void push(int x){
        if(s1.empty()) s1.push(x);
        else{
            while(!s1.empty()){
                s2.push(s1.pop());
            }
            s2.push(x);
            while(!s2.empty()){
                s1.push(s2.pop());
            }
        }
    }

    public int pop(){
        if(s1.empty()) return -1;
        return s1.pop();
    }

    public boolean isEmpty(){
        return s1.empty();
    }

    public int peek(){
        return s1.peek();
    }
}

Test class for above implementation would be:

package test;

import com.company.QueueWithStack;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
 * Created by sangar on 23.9.18.
 */
public class QueueWithStackTest {

    QueueWithStack tester = new QueueWithStack();
    @Test
    public void queueTest() {

        tester.push(2);
        tester.push(3);
        tester.push(5);
        tester.push(1);

        assertEquals(2, tester.pop());
        assertEquals(3, tester.pop());
        assertEquals(5, tester.peek());
        assertEquals(false, tester.isEmpty());
    }
}

Can we do better than O(n) while pushing element in queue?

Queue with stack : Push O(1), pop amortized complexity O(1) implementation

Push()
What if we push on s1 as it is. What does it change? It make push operation on queue O(1).

Pop()
How does it impacts pop operation? If we pop all element from s1 and push them onto s2, at the top of s2 is actually the element we need. Also, due to this pop and push operation, s2 now contains all the elements in correct pop order for queue.
So idea is to always push in s1 as it is, however when popping out, check if s2 is empty or not? If not, then pop from s2 and return, if it is empty, pop all elements from s1 and push them all on s2 and return the top.

implement queue with stacks

How does it impact the performance? Well, it is true that if there is not element in s2, we have pop and push on s2, which has complexity of O(n). HOwever, all subsequent pop operations are O(1), this is called amortized complexity of O(1).

Empty()
Queue to be empty, there should not any element in either s1 or s2.

Peek()
If s2 is empty, then pop from s1 and push on to s2 and then return peek of s2.

package com.company;

import java.util.Stack;

/**
 * Created by sangar on 23.9.18.
 */
public class QueueWithStackOptimized {
    private Stack<Integer> s1;
    private Stack<Integer> s2;
    private int front;

    public QueueWithStackOptimized(){
        s1 = new Stack<>();
        s2 = new Stack<>();
    }

    public void push(int x){
        if(s1.empty()) front = x;
        s1.push(x);
    }

    public int pop(){
        if(!s2.empty()) return s2.pop();
        if(!s1.empty()) return -1;

        while(!s1.empty()){
            s2.push(s1.pop());
        }
        return s2.pop();
    }

    public boolean isEmpty(){
        return s1.empty() && s2.empty();
    }

    public int peek(){
        if(!s2.empty()) return s2.peek();

        return front;
    }
}

Complexity of peek function is again amortized to O(1). Can you write test cases for implemented queue?

Reference : Leetcode

Please share if there is something wrong or missing. If you want to have personal coaching from our experienced coaches, please reach out to us at communications@algorithmsandme.com

Matching parenthesis problem

Matching parenthesis problem

We understood the concept of stack data structure in last post. Let’s discuss matching parenthesis problemwhich applies those concept. Problem statement is :

Given a string of parenthesis ‘(‘ and ‘)’, write a function which returns true if there are matching pairs and false if there are not. A matching pair means, there should be a closing parenthesis for an opening one, in correct order.

For example : '((()))', function should return TRUE, but ')(())' will return FALSE. Special case would be when there are equal number of parenthesis, closing and opening, but they are not in perfect order, hence function should return false in that case.

Parenthesis matching problem : Line of thoughts

For each closing parenthesis, we need a corresponding opening parenthesis. There are two possibilities : Either we find one or we do not find one. If we do not find one, we can say that string does not contain matching parenthesis.
If there is corresponding opening parenthesis, then that opening parenthesis cannot be matched with any other closing parenthesis.

Also, note that every closing parenthesis will match with the most recent opening parenthesis if there is one. That means we are looking at a order where the parenthesis which came last needs to be fetched first, typical last in first out pattern, which is best implemented by stack.

For asserting that the current closing parenthesis is in sync with what we have already seen, we just need to check if current parenthesis completes a pair with opening parenthesis we last seen. Next closing parenthesis should complete pair with the one prior to last and so on.

Parenthesis matching problem : Algorithm

  1. For each character of input string
  2. If character is opening parenthesis '(', put it on stack.
  3. If character is closing parenthesis ')'
    1. Check top of stack, if it is '(' , pop and move to next character.
    2. If it is not '(', return false
  4. After scanning the entire string, check if stack is empty. If stack is empty, return true else return false.

Matching parenthesis problem : Implementation

package com.company;

import java.util.Stack;

/**
 * Created by sangar on 21.9.18.
 */
public class ParenthesisMatch {

    public static boolean isMatchingParenthesis(String s) {
        Stack<Character> stack = new Stack<>();

        if (s == null) return true;

        int len = s.length();
        for(int i=0; i<len; i++){
            switch(s.charAt(i)){
                case '(' :
                    stack.push(s.charAt(i));
                    break;
                case ')':
                    //If stack is empty, then there is an extra closing parenthesis
                    if(stack.isEmpty()) return false;
                    stack.pop();
                    break;
                default:
                    return false;
            }
        }
        //If stack is empty that means it's a matching parenthesis
        return stack.empty();
    }

    public static void main(String[] args) {
        String s = "()))";
        System.out.println(isMatchingParenthesis(s));
    }
}

Complexity of parenthesis matching algorithm is O(N) time to scan N length string and O(N) extra space for stack.
This problem is quite simple to solve, so if you are asked this question in interview, most probably interviewer wants to understand can you think of good test cases and put your code to test against them. Below are the few test cases you can try your code on.
Test cases

1. ((())) : True
2. ())) : False
3. )((( : False
4. ( : False
5 Empty string : True
6. NULL pointer : False

Can you try solving this problem now on HackerEarth

Please share if there is something wrong or missing. If you are interested to take personal coaching from our experience teachers, please reach out to us at communications@algorithmsandme.com

Stack data structure and applications

Stacks data structure

What is stack data structure? Stack is a dynamic data structure, where information is stack over one another. In common terminology, we use the stack with same meaning like stack of trays or stack of pancakes. Extend the concept of stack in real life, you remove the tray at the top before moving tray below it. So the tray which goes last on to stack, come off the stack first. This pattern is called as Last In First Out or LIFO.

For any data structure, three operations should be considered : How data can be added to it, how data can be removed from it and how data can be read from it? Let’s discuss these operations on stack one by one.

Operations on stack

Write operation on stack is commonly known as push. Push operation writes information on to top of the stack.Complexity of push operation is O(1) as no iteration is required.

Read operation is known as pop, where element at the top of stack is removed. Complexity of pop is also O(1).
stack data structure

Another operation which is commonly used is isEmpty(), this checks if there are any elements in stack at present.

What if you just want to check the top element of stack but do not want to remove it from stack? Then operation called peek() is for you. It reads the top element, however does not remove it from stack.

Since stack can dynamically increase and decrease in size based on push and pop operation, we need to keep track of the top of the stack.

Stack can be represented as recursive structure i.e if we remove the top of the stack, remaining N-1 element is again a stack.

Let’s take an example to see how push and pop operations on stack actually follow Last In First Out pattern.

stack data structure

Implementation of stack data structure

Stacks can be implemented in two ways, first where underlying data storage is an array and second where underlying storage is linked list. Refer difference between array and linkedlist to understand more that impacts stack implementation.

1. In Array based implementation of stack implementation, underlying data structure used is an array. We keep an extra variable (top) to keep track of number of elements present in stack at given time. When we push an element on to stack, increase the top. When we pop an element from stack, we decrease the top.

In this implementation, top being -1 represents empty stack and top equal to N-1, N being the size of array, represents stack full. Push and pop operations are of O(1) complexity.

Drawback of this implementation is that we need to define stack size statically at the compile time and changing it at runtime dynamically would be overhead.

#include<stdio.h>
#include<stdlib.h>

#define STACK_SIZE 100

typedef struct stack{
        int top;
        int items[STACK_SIZE];
}stack;
 
void push(stack *ms, int item){
   if(ms->top < STACK_SIZE-1){
       ms->items[++(ms->top)] = item;
   }
   else {
       printf("Stack is full\n");
   }
}

//Get the element at the top of stack and remove it from stack
int pop (stack *ms){
   if(ms->top > -1 ){
       return ms->items[(ms->top)--];
   } 
   else{
       printf("Stack is empty\n");
   }
}

//Get the element at the top of stack without removing it.
int peek(stack ms){
  if(ms.top < 0){
      printf("Stack empty\n");
      return 0;
   }
   return ms.items[ms.top];
}

//Function to check if stack is empty or not?
int isEmpty(stack ms){
   if(ms.top < 0) return 1;
   else return 0;
}

2. In Linked List based implementation of stack implementation, underlying data structure used is linked list. Every node in the linked list represents an element in stack. Every push operation adds a node at the head of linked list and every pop operation removes a node from head of the linked list.

In this implementation too, push and pop operations are of O(1) complexity. Also stack can grow as much as required. Head being NULL represents empty stack.

Drawback is we need to store 4 bytes extra as next pointer for each element.

#include <stdio.h>

#include<stdlib.h>
#include<stdio.h>

typedef struct node{
    int data;
    struct node *next;
} Node;

/* Create a node of linked list */
Node * createNode(int val){
  Node * temp = (Node *)malloc(sizeof(Node));
  if(temp){
    temp->data = val;
    temp->next = NULL;
  }
  return temp;
}
 
/* This function inserts node at the head of linked list */
void push(Node **headRef, int data){
    Node *newNode  = createNode(data);
    newNode->next = *headRef;
    *headRef  = newNode;
}

/* This function removes node from the head of linked list */
Node * pop(Node **headRef, int data){
    if(!(*headRef)) return NULL;
	
    Node * poppedNode = *headRef;
    *headRef = (*headRef)->next;
    return poppedNode;
}

/* This function return node at the head of linked list */
Node * peek(Node **headRef, int data){
    if(!(*headRef)) return NULL;
	
    return (*headRef);
} 

int isEmpty(Node **headRef){
    return (*headRef == NULL);
}

Stack Overflow

You must have heard the term stack overflow. Why does it occur and how does it relates to stack data structure?
Stack supports function call paradigm in programming languages. When a function in your program calls another function (which can be the same function in case of recursion), program management module in operating system stores quite a few things to have safe return. This includes : parameters passed to function, return values, return pointers. As you go deep into function calls, one function calling second, then second calling third and so on, each of this successive call takes a frame of system stack as explained above. Depending on the size of information you are putting on stack frame in each call, sooner or later, stack will be full, as it has limited memory allocated in kernel.

Now when you try to add one more frame because you are calling another function, there is no space. That’s when stack overflow happens.

Why do you think function call information is store on stack and not on any other data structure? Let’s say your program calls function A from function B, which in turn was called from function C. When you are returning from function A, you want to return to calling address in function B and not function C. So, you want to return back in reverse order of calling sequence, LIFO, that why stack is best data structure.

It is recommended to implement production code in iterative way rather than recursive using application level stacks. As application stack is allocated from heap, it can grow much bigger than kernel stack. Also, you can select what to put on stack. If you look at iterative preorder traversal, iterative postorder traversal interview problems, they are nothing but to test your knowledge of stack data structure. To read more on stack overflow, please refer : stack overflow

Application of stack : browser back button

Let’s solve a problem and see how stack data structure can be used to solve problems. Problem statement is : Implement back button on browser. When you click on back button, you go to previous site you visited. You press it again, than you go to site prior to it and so on.

Do you see application stack here? When you go back, you want to land on the last site you visited. What pattern is this? Of course, it last in first out which can be implemented using stack.
So idea is to whenever you move to new site or page, current page is added to stack. If you press back button, top of the stack is popped and return to you as current page. If you press again, top of the stack contains now the page you visited before current page, so land there.

browser back button using stack

There can one more complexity added to this problem, which is you want to implement forward button too. In that case, whenever you pop out a page from back stack, put it into a new stack called forward stack. Can you run through some examples and see if that actually works?

Please share if there is something wrong or missing. If you are interested in taking personal coaching by our experienced teachers, please reach out to us at communications@algorithmsandme.com