Stack
A stack is a linear data structure in which follows a particular order in which the operations are performed. The insertion and deletion of elements are performed in Last in First out (LIFO) order or First in Last out (FILO) order. We can say that the insertion and deletion can be done at one end only.
There are many real-life examples of a stack. For example, the
plates are stacked over another in the canteen. The plate which is at the top
is the first one to be removed which means the plate which is at the bottom
most position remains in the stack for the longest period of time.
Basic Operations of Stack
The following are the basic operations performed in the stack:
Push: Adds an
item to 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 reverse order in which they
are pushed. If the stack is empty, then it is said to be an Underflow
condition.
Top: Returns
top element of stack.
isEmpty: Return true if stack is empty, else
false.
The following are the various operations of Stack:
Time Complexity of operations on Stack
The push(), pop(), isEmpty and top() methods have time complexity of O(1). As we do not run any loop on any of these operations, the time complexity is O(1).
Stack Implementation
The stack can be implemented in following two ways namely,
Implementation
of Stack using Array
The stack can be represented in memory with the use of Arrays. To
perform this stack operation, we need to maintain a linear array Stack, a
pointer variable top which contains the top element.
Example
The following is the C implementation of stack using Array:
#include <stdio.h> #include<stdlib.h> int top = -1; int stk[5]; void push(int x) { if(top > 4) { printf("Stack overflow"); return; } stk[++top] = x; printf("Inserted the value %d\n", x); } void pop() { if(top < 0) { printf("Stack underflow"); return; } printf("The deleted element is %d\n", stk[top--]); } void display() { if (top < 0) { printf("Stack is empty\n"); return; } for (int i = top; i >= 0; i--) { printf("%d\t", stk[i]); } } int main() { int ch; int val; while (1) { printf("\n1.push 2.pop 3.display 4.exit\nEnter ur choice: "); scanf("%d", &ch); switch (ch) { case 1: printf("Enter the element: "); scanf("%d", &val); push(val); break; case 2: pop(); break; case 3: display(); break; case 4: exit(0); } } }
Output
1.push 2.pop 3.display 4.exit Enter ur choice: 1 Enter the element: 5 Inserted the value 5 1.push 2.pop 3.display 4.exit Enter ur choice: 1 Enter the element: 10 Inserted the value 10 1.push 2.pop 3.display 4.exit Enter ur choice: 1 Enter the element: 15 Inserted the value 15 1.push 2.pop 3.display 4.exit Enter ur choice: 2 The deleted element is 15 1.push 2.pop 3.display 4.exit Enter ur choice: 3 10 5 1.push 2.pop 3.display 4.exit
Pros – Easy to
implement. Memory is saved as pointers are not involved.
Cons – It is
not dynamic. It doesn’t grow and shrink depending on needs at runtime.
Implementation
of Stack using Linked List
The Stack can be implemented using Linked List which can grow and
shrink according to the needs at runtime.
Example
The following is the C implementation of Stack using Linked list:
#include<stdio.h> #include<stdlib.h> struct node { int data; struct node *link; }*top; void push(int x) { struct node *temp; temp=(struct node *)malloc(sizeof(struct node)); temp->data=x; temp->link=top; top=temp; } void pop() { struct node *temp; if(top==NULL) { printf("Stack is empty"); return; } temp=top; top=top->link; free(temp); } void print() { struct node *temp=top; while(temp!=NULL) { printf("%d\t",temp->data); temp=temp->link; } printf("\n"); } void main() { push(2); push(3); push(6); print(); printf("Pop the top element\n"); pop(); printf("Push 10 to the stack\n"); push(10); print(); }
Output
6 3 2 Pop the top element Push 10 to the stack 10 3 2
Pros – The
linked list implementation of Stack can grow and shrink according to the needs
at the runtime.
Cons –
Requires extra memory due to involvement of pointers.
Applications of Stack
The following are the various applications of Stack data
structure:
Expression Evaluation – Stack is used to evaluate prefix, postfix
and infix expressions.
Expression
Conversion – An expression can be represented in prefix, postfix and infix
notation. Stack can be used to convert one form of expression to another.
Syntax
parsing – Many compilers use stack data structure for parsing the syntax
of expressions, program blocks, etc.
Parenthesis
checking – Stack is used to check the proper opening and closing of
parenthesis.
Backtracking – The
stack is used to backtrack the steps while solving some problem. For example,
suppose we are finding the solution for Maze problem. We choose a path and
after following it we may realize it is wrong. Now we can go back to the
beginning of the path and to start with the new path. This can be achieved
easily using Stack.
String
Reversal – Stack is used to reverse a string. We push the characters of
string one by one and finally pop characters from the stack.
Function call – Stack is used to keep track of information about the active functions and subroutines.