Theory PDF
Theory PDF
The Stack is a linear data structure which follows a particular order in which the
operations are performed. The order may be LIFO(Last In First Out) or FILO(First In
Last Out).
• The LIFO order says that the element which is inserted at the last in the Stack
will be the first one to be removed. In LIFO order insertion takes place at the
rear end of the stack and deletion occurs at the front of the stack.
• The FILO order says that the element which is inserted at the first in the Stack
will be the last one to be removed. In FILO order insertion takes place at the
rear end of the stack and deletion occurs at the front of the stack.
Mainly the following three basic operations are performed in the stack:
• Push: Adds an item in the stack. If the stack is full, then it is said to be an
Overflow condition.
• Pop: Removes an item from the stack. The items are popped in the reversed
order in which they are pushed. If the stack is empty, then it is said to be an
Underflow condition.
• Peek or Top: Returns top element of stack.
• Using array
• Using linked list
C++
#include<bits/stdc++.h>
class Stack
{
int top;
public:
int a[MAX]; //Maximum size of Stack
bool Stack::push(int x)
{
if (top >= (MAX-1))
{
cout << "Stack Overflow";
return false;
}
else
{
a[++top] = x;
cout<<x <<" pushed into stackn";
return true;
}
}
int Stack::pop()
{
if (top < 0)
{
cout << "Stack Underflow";
return 0;
}
else
{
int x = a[top--];
return x;
}
}
bool Stack::isEmpty()
{
return (top < 0);
}
return 0;
}
Run
Java
class Stack
{
static final int MAX = 1000;
int top;
int a[] = new int[MAX]; // Maximum size of Stack
boolean isEmpty()
{
return (top < 0);
}
Stack()
{
top = -1;
}
boolean push(int x)
{
if (top >= (MAX-1))
{
System.out.println("Stack Overflow");
return false;
}
else
{
a[++top] = x;
System.out.println(x + " pushed into stack");
return true;
}
}
int pop()
{
if (top < 0)
{
System.out.println("Stack Underflow");
return 0;
}
else
{
int x = a[top--];
return x;
}
}
}
// Driver code
class Main
{
public static void main(String args[])
{
Stack s = new Stack();
s.push(10);
s.push(20);
s.push(30);
System.out.println(s.pop() + " Popped from stack");
}
}
Run
Output :
10 pushed into stack
C++
#include <bits/stdc++.h>
stackNode->next = *root;
*root = stackNode;
return popped;
}
return root->data;
}
// Driver Code
int main()
{
struct StackNode* root = NULL;
push(&root, 10);
push(&root, 20);
push(&root, 30);
return 0;
}
Run
Java
StackNode root;
StackNode(int data) {
this.data = data;
}
}
if (root == null) {
root = newNode;
} else {
StackNode temp = root;
root = newNode;
newNode.next = temp;
}
System.out.println(data + " pushed to stack");
}
sll.push(10);
sll.push(20);
sll.push(30);
10 pushed to stack
20 pushed to stack
30 pushed to stack
30 popped from stack
Top element is 20
Pros: The linked list implementation of stack can grow and shrink according to the
needs at runtime.
Cons: Requires extra memory due to involvement of pointers.
Applications of stack:
Syntax:
Here,
data_type: This defines the type of data to be
stored in the stack.
stack_name: This specifies the name of the stack.
Implementation:
int main ()
{
stack <int> s;
s.push(10);
s.push(30);
s.push(20);
s.push(5);
s.push(1);
return 0;
}
Run
Output:
The stack is : 1 5 20 30 10
s.size() : 5
s.top() : 1
s.pop() : 5 20 30 10
Stack class in Java
Java Collection framework provides a Stack class which models and implements the
Stack data structure. The class is based on the basic principle of last-in-first-out. In
addition to the basic push and pop operations, the class provides three more
functions of empty, search and peek. The class can also be said to extend Vector
and treats the class as a stack with the five mentioned functions. The class can also
be referred to as the subclass of Vector.
The class supports one default constructor Stack() which is used to create an empty
stack.
Below program shows a few basic operations provided by the Stack class:
import java.io.*;
import java.util.*;
class Test
{
// Pushing element on the top of the stack
static void stack_push(Stack<Integer> stack)
{
for(int i = 0; i < 5; i++)
{
stack.push(i);
}
}
if(pos == -1)
System.out.println("Element not found");
else
System.out.println("Element is found at position " + pos);
}
stack_push(stack);
stack_pop(stack);
stack_push(stack);
stack_peek(stack);
stack_search(stack, 2);
stack_search(stack, 6);
}
}
Run
Output:
Pop :
4
3
2
1
0
Element on stack top : 4
Element is found at position 3
Element not found
The corresponding expression in postfix form is: abc*+d+. The postfix expressions
can be evaluated easily using a stack. We will cover postfix expression evaluation in
a separate post.
Algorithm to Convert an Infix expression to Postfix:
#include<bits/stdc++.h>
using namespace std;
int l = s.length();
string ns;
st.push('(');
ns += c;
}
if(st.top() == '(')
{
char c = st.top();
st.pop();
}
}
// If an operator is scanned
else{
while(st.top() != 'N' && prec(s[i]) <= prec(st.top()))
{
char c = st.top();
st.pop();
ns += c;
}
st.push(s[i]);
}
}
// Driver Code
int main()
{
string exp = "a+b*(c^d-e)^(f+g*h)-i";
infixToPostfix(exp);
return 0;
}
Run
Java
import java.util.Stack;
class Test
{
// A utility function to return precedence
// of a given operator
// Higher the returned value means
// higher the precedence
static int Prec(char ch)
{
switch (ch)
{
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
}
return -1;
}
return result;
}
// Driver method
public static void main(String[] args)
{
String exp = "a+b*(c^d-e)^(f+g*h)-i";
System.out.println(infixToPostfix(exp));
}
}
Run
Output:
abcd^e-fgh*+^*+i-
Example: Let the given expression be "2 3 1 * + 9 -". We will first scan all elements
one by one.
#include <iostream>
#include <string.h>
#include<stack>
int i;
switch (exp[i])
{
case '+': st.push(val2 + val1); break;
case '-': st.push(val2 - val1); break;
case '*': st.push(val2 * val1); break;
case '/': st.push(val2/val1); break;
}
}
}
return st.top();
}
// Driver Code
int main()
{
char exp[] = "231*+9-";
cout<<"postfix evaluation: "<< evaluatePostfix(exp);
return 0;
}
Run
Java
Output:
postfix evaluation: -4
1. It supports only 4 binary operators '+', '*', '-' and '/'. It can be extended for
more operators by adding more switch cases.
2. The allowed operands are only single-digit operands. The program can be
extended for multiple digits by adding a separator like space between all
elements (operators and operands) of the given expression.
Below given is the extended program which allows operands having multiple digits.
C++
#include <bits/stdc++.h>
using namespace std;
int i;
i--;
switch (exp[i])
{
case '+': st.push(val2 + val1); break;
case '-': st.push(val2 - val1); break;
case '*': st.push(val2 * val1); break;
case '/': st.push(val2/val1); break;
}
}
}
return st.top();
}
// Driver code
int main()
{
char exp[] = "100 200 + 2 / 5 * 7 +";
cout << evaluatePostfix(exp);
return 0;
}
Run
Java
// Java proram to evaluate value of a postfix
// expression having multiple digit operands
import java.util.Stack;
class Test1
{
// Method to evaluate value of a postfix expression
static int evaluatePostfix(String exp)
{
//create a stack
Stack<Integer> stack = new Stack<>();
switch(c)
{
case '+':
stack.push(val2+val1);
break;
case '-':
stack.push(val2- val1);
break;
case '/':
stack.push(val2/val1);
break;
case '*':
stack.push(val2*val1);
break;
}
}
}
return stack.pop();
}
Method 1 (Divide the space in two halves): A simple way to implement two stacks
is to divide the array into two halves and assign the half space to the first stack and
the other half to the second stack, i.e., use arr[0] to arr[n/2] for stack1, and arr[(n/2) +
1] to arr[n-1] for stack2 where arr[] is the array to be used to implement two stacks
and size of array be n.
The problem with this method is an inefficient use of array space. A stack push
operation may result in stack overflow even if there is space available in arr[]. For
example, say the array size is 6 and we push 3 elements to stack1 and do not push
anything to the second stack2. When we push the 4th element to stack1, there will
be overflow even if we have space for 3 more elements in the array.
#include<iostream>
#include<stdlib.h>
class twoStacks
{
int *arr;
int size;
int top1, top2;
public:
twoStacks(int n) // constructor
{
size = n;
arr = new int[n];
top1 = -1;
top2 = size;
}
// Driver Program
int main()
{
twoStacks ts(5);
ts.push1(5);
ts.push2(10);
ts.push2(15);
ts.push1(11);
ts.push2(7);
ts.push2(40);
return 0;
}
Run
Java
class TwoStacks
{
int size;
int top1, top2;
int arr[];
// Constructor
TwoStacks(int n)
{
arr = new int[n];
size = n;
top1 = -1;
top2 = size;
}
}
return 0;
}
The time complexity of all of the four push and pop operations of both stacks is
O(1).
Sample Problems on Stack
[1 2 3 4 5]
[5 4 3 2 1]
Solution - We will traverse the linked list and push all the nodes of the linked list to
the stack. Since stack have property of Last In, First Out, List is automatically
reversed when we will pop the stack elements one by one.
Pseudo Code
void printreverse(Node *head)
{
stack < Node* > s
current = head
while(current != NULL)
{
s.push(current)
current = current->next
}
while( ! s.empty())
{
node = s.top()
print(node->data)
s.pop()
}
}
Time Complexity : O(n)
Auxiliary Space : O(n)
Problem #2 : Check for balanced parentheses in an
expression
Description - Given an expression string exp , we have to check whether the pairs
and the orders of { “ , ” } , ( “ , ” ) and [ “ , ” ] are correct in exp. For example -
Input : [ ( ) ] { } { [ ( ) ( ) ] ( ) }
Output : true
Input : [ ( ] )
Output : false
Solution : Follow the streps below -
o If the current character is a starting bracket ‘(‘ or ‘{‘ or ‘[‘ then push it to
stack.
o If the current character is a closing bracket ‘)’ or ‘}’ or ‘]’ then pop from
stack and if the popped character is the matching starting bracket then
fine else parenthesis are not balanced.
3. After complete traversal, if there is some starting bracket left in stack then “not
balanced”.
Pseudo Code
// function to check if paranthesis are balanced
bool areParanthesisBalanced(string expr)
{
stack < char > s
if (expr[i]=='('||expr[i]=='['||expr[i]=='{') {
s.push(expr[i])
continue
}
// stack can not be empty for closing bracket
if s.empty()
return false
switch (expr[i]) {
case ')': {
x = s.top()
s.pop()
if (x=='{' || x=='[')
return false
break
}
case '}': {
x = s.top();
s.pop();
if (x=='(' || x=='[')
return false
break
}
case ']': {
x = s.top();
s.pop();
if (x =='(' || x == '{')
return false
break
}
}
}
// Check Empty Stack
return (s.empty())
}
Time Complexity : O(n)
Auxiliary Space : O(n)
Pseudo Code
// Next greater Element
void printNGE(arr, n)
{
stack < int > s
s.push(arr[0])
for i=0 to n-1 {
if (s.empty()) {
s.push(arr[i])
continue
}
while (s.empty() == false && s.top() < arr[i]) {
print(s.top() + "-->" + arr[i])
s.pop()
}
s.push(arr[i])
while (s.empty() == false) {
print(s.top() + "-->" + -1)
s.pop()
}
}
}
Time Complexity : O(n)
Auxiliary Space : O(n)