Unit V-Stack
Basic concept, stack Abstract Data Type,
Representation of Stacks Using Sequential
Organization, stack operations, Multiple Stacks,
Applications of Stack- Expression Evaluation and
Conversion, Polish notation and expression
conversion, Need for prefix and postfix
expressions, Postfix expression evaluation, Linked
Stack and Operations. Recursion- concept,
variants of recursion- direct, indirect, tail and tree,
Backtracking algorithmic strategy, use of stack in
backtracking.
Basic concept: A stack is a conceptual structure consisting of
a set of homogeneous elements and is based on the principle of
last in first out (LIFO). It is a commonly used abstract
data type with two major operations, namely push and pop.
Push and pop are carried out on the topmost element, which
is the item most recently added to the stack. The push operation
adds an element to the stack while the pop operation removes
an element from the top position. The stack concept is used in
programming and memory organization in computers.
stack Abstract Data Type:
The stack abstract data type is defined by the following
structure and operations. A stack is structured, as described
above, as an ordered collection of items where items are added
to and removed from the end called the “top.” Stacks are
ordered LIFO. The stack operations are given below.
● Stack() creates a new stack that is empty. It needs no
parameters and returns an empty stack.
● push(item) adds a new item to the top of the stack. It needs the
item and returns nothing.
● pop() removes the top item from the stack. It needs no
parameters and returns the item. The stack is modified.
● isEmpty() tests to see whether the stack is empty. It needs no
parameters and returns a boolean value.
● size() returns the number of items on the stack. It needs no
parameters and returns an integer.
Representation of Stacks Using Sequential Organization ,
stack operations
Int MAX 10
Int stack[MAX];
Int top=-1;
Stack Operations using Array
A stack can be implemented using array as follows...
Before implementing actual operations, first follow the below
steps to create an empty stack.
● Step 1 - Include all the header files which are used in
the program and define a constant 'SIZE' with specific
value.
Int size 10;
● Step 2 - Declare all the functions used in stack
implementation.
Int push(int);
Int pop();
Int disp(int)
● Step 3 - Create a one dimensional array with fixed size
(int stack[SIZE])
Int st[size]
● Step 4 - Define a integer variable 'top' and initialize
with '-1'. (int top = -1)
Int top=-1;
● Step 5 - In main method, display menu with list of
operations and make suitable function calls to perform
operation selected by the user on the stack.
push(value) - Inserting value into the stack
In a stack, push() is a function used to insert an element into
the stack. In a stack, the new element is always inserted
at top position. Push function takes one integer value as
parameter and inserts that value into the stack. We can use the
following steps to push an element on to the stack...
● Step 1 - Check whether stack is FULL. (top == SIZE-1)
If(top==size-1)
● Step 2 - If it is FULL, then display "Stack is FULL!!!
Insertion is not possible!!!" and terminate the
function.
● Step 3 - If it is NOT FULL, then increment top value by
one (top++) and set stack[top] to value (stack[top] =
value).
0 1 2 3 4
10 20 60 50
Algorithm_push()
If TOP >= SIZE – 1 then // Stack Overflow indicating that the
Stack is FULL.
TOP = TOP + 1
STACK [TOP] = ELEMENT
pop() - Delete a value from the Stack
In a stack, pop() is a function used to delete an element from
the stack. In a stack, the element is always deleted
from top position. Pop function does not take any value as
parameter. We can use the following steps to pop an element
from the stack...
● Step 1 - Check whether stack is EMPTY. (top == -1)
● Step 2 - If it is EMPTY, then display "Stack is
EMPTY!!! Deletion is not possible!!!" and terminate
the function.
● Step 3 - If it is NOT EMPTY, then
delete stack[top] and decrement top value by one
(top--).
0 1 2 3 4
10 20 60
Algorithm_pop()
If TOP = -1 then // Stack Underflow indicating that the Stack
is EMPTY.
Return STACK [TOP]
TOP = TOP - 1
display() - Displays the elements of a Stack
We can use the following steps to display the elements of a
stack...
● Step 1 - Check whether stack is EMPTY. (top == -1)
● Step 2 - If it is EMPTY, then display "Stack is
EMPTY!!!" and terminate the function.
● Step 3 - If it is NOT EMPTY, then define a variable 'i'
and initialize with top. Display stack[i] value and
decrement i value by one (i--).
● Step 3 - Repeat above step until i value becomes '0'.
0 1 2 3 4
10 20 60 70
I=top;i>=0;i—
Ele=st[top] ele=st[3]= ele=70
Ele=st[top] ele=st[2]= ele=60
Ele=st[top] ele=st[1]= ele=20
Ele=st[top] ele=st[0]= ele=10
Multiple Stack:
When a stack is created using single array, we can not able to store large
amount of data, thus this problem is rectified using more than one stack in the
same array of sufficient array. This technique is called as Multiple Stack.
When an array of STACK[n] is used to represent two stacks, say Stack A and
Stack B. Then the value of n is such that the combined size of both the
Stack[A] and Stack[B] will never exceed n. Stack[A] will grow from left to
right, whereas Stack[B] will grow in opposite direction ie) right to left.
0 1 2 3 4 5 6 7 8 9
111 222 444 555 666 777 888 999 1100 333
If(top1<=top2-1)||(top2>top1+1)
overflow
Top1=-1,top2=max
St[top1]=111; st[top2]=333
C program - Multiple Stack
#include <stdio.h>
#include <malloc.h>
#define MAX 10
int stack[MAX], topA = -1, topB = MAX;
void pushA(int val)
{
if(topA == topB-1)
printf("\n Overflow");
else
{
topA+=1;
stack[topA] = val;
}
}
int popA()
{
int val;
if(topA == -1)
{
printf("\n Underflow");
val = -999;
}
else
{
val = stack[topA];
topA--;
}
return val;
}
void display_stackA()
{
int i;
if(topA == -1)
printf("\n Stack A is empty");
else
{
for(i = topA;i >= 0;i--)
printf("\t %d",stack[i]);
}
}
void pushB(int val)
{
if(topB-1 == topA)
printf("\n Overflow");
else
{
topB-=1;
stack[topB] = val;
}
}
int popB()
{
int val;
if(topB == MAX)
{
printf("\n Underflow");
val = -999;
}
else
{
val = stack[topB];
topB++;
}
}
void display_stackB()
{
int i;
if(topB == MAX)
printf("\n Stack B is Empty");
else
{
for(i = topB; i < MAX;i++)
printf("\t %d",stack[i]);
}
}
int main()
{
int option, val;
do
{
printf("\n -----Menu----- ");
printf("\n 1. PUSH a element into Stack A");
printf("\n 2. PUSH a element into Stack B");
printf("\n 3. POP a element from Stack A");
printf("\n 4. POP a element from Stack B");
printf("\n 5. Display the Stack A");
printf("\n 6. Display the Stack B");
printf("\n 7. Exit");
printf("\n Enter your choice");
scanf("%d",&option);
switch(option)
{
case 1:
printf("\n Enter the value to push on stack A :");
scanf("%d",&val);
pushA(val);
break;
case 2:
printf("\n Enter the value to push on stack B:");
scanf("%d", &val);
pushB(val);
break;
case 3:
if(val != -999)
printf("\n The value popped from Stack A = %d", val);
break;
case 4:
if(val != -999)
printf("\n The value popped from Stack B = %d",val);
break;
case 5:
printf("\n The contents of Stack A are :\n");
display_stackA();
break;
case 6:
printf("\n The contents of Stack B are :\n");
display_stackB();
break;
}
}while(option != 7);
return 0;
}
Applications of Stack- Expression Evaluation and
Conversion, Polish notation and expression conversion
What is an Expression?
In any programming language, if we want to perform any
calculation or to frame a condition etc., we use a set of symbols
to perform the task.
These set of symbols makes an expression.
An expression can be defined as follows...
An expression is a collection of operators and operands that represents a
specific value.
In above definition, operator is a symbol which performs a
particular task like arithmetic operation or logical operation or
conditional operation etc.,
Operands are the values on which the operators can perform
the task. Here operand can be a direct value or variable or
address of memory location.
A+B-C/D*F^U
Expression Types
Based on the operator position, expressions are divided into
THREE types. They are as follows...
1. Infix Expression
2. Postfix Expression
3. Prefix Expression
Infix Expression
In infix expression, operator is used in between the operands.
The general structure of an Infix expression is as follows...
Operand1 Operator Operand2
Example
Postfix Expression
In postfix expression, operator is used after
operands. We can say that "Operator follows
the Operands".
The general structure of Postfix expression is as
follows...
Operand1 Operand2 Operator
Example
Prefix Expression
In prefix expression, operator is used before
operands. We can say that "Operands follows
the Operator".
The general structure of Prefix expression is as
follows...
Operator Operand1 Operand2
Example
Convert Infix to Postfix Expression
To convert infix expression to postfix expression, we will use the stack data structure. By
scanning the infix expression from left to right, when we will get any operand, simply add
them to the postfix form, and for the operator and parenthesis, add them in the stack
maintaining the precedence of them.
Note: Here we will consider only {+, −,∗,/, ^} operators, other operators are neglected.
Algorithm
infixToPostfix(infix)
Input − Infix expression.
Output − Convert infix expression to postfix form.
Begin
initially push some special character say # into the stack
for each character ch from infix expression, do
if ch is alphanumeric character, then
add ch to postfix expression
else if ch = opening parenthesis (, then
push ( into stack
else if ch = ^, then //exponential operator of higher precedence
push ^ into the stack
else if ch = closing parenthesis ), then
while stack is not empty and stack top ≠ (,
do pop and add item from stack to postfix expression
done
pop ( also from the stack
else
while stack is not empty AND precedence of ch <= precedence of stack top element, do
pop and add into postfix expression
done
push the newly coming character.
done
while the stack contains some remaining characters, do
pop and add to the postfix expression
done
return postfix
End
Convert Infix to Prefix Expression
Algorithm
infixToPrefix(infix)
Input − Infix expression to convert into prefix form.
Output − The prefix expression.
Begin
reverse the infix expression
for each character ch of reversed infix expression, do
if ch = opening parenthesis, then
convert ch to closing parenthesis
else if ch = closing parenthesis, then
convert ch to opening parenthesis
done
postfix := find transformed infix expression to postfix expression
prefix := reverse recently calculated postfix form
return prefix
End
Prefix to Infix Conversion
In this problem, we are given a prefix expression.
Our task is to print the infix conversion of the
given expression.
Prefix expression is those expressions which have
operators before the operands.
Example: +AB.
Infix expressions are those expressions which have
operators between the operands.
Example: A+B
Input: prefix : /+LM/NX
Output: infix : (L+M) / (N/X)
To solve this problem, we will be using the stack
data structure. We will traverse the prefix
expression in reverse order of the expression. And
for each element of the expression check for these
cases.
If element is operand -> push(element) in stack.
If element is operator -> 2Xpop(topofstack) and
push in order as a string = operand - operator -
operand.
Finally, after traversal, the top of the stack will
contain a string which is the infix conversion, print
it.
Program to show the implementation of our
solution.
Postfix to Infix
In this problem, we are given expression in postfix form and our task is to print the infix
form of the expression.
Infix expression is an expression in which the operator is in the middle of operands,
like operand operator operand.
Postfix expression is an expression in which the operator is after operands, like operand
operator.
Postfix expressions are easily computed by the system but are not human readable. So this
conversion is required. Generally reading and editing by the end-user is done on infix
notations as they are parenthesis separated hence easily understandable for humans.
Let’s take an example to understand the problem
Input − xyz/*
Output − (x * (y/z))
To solve this problem, we will use the stack data structure. And traverse the postfix
expression one by one and then check for the following case −
Case 1 − if the operand is found, push it in the stack.
Case 2 − if an operator is found, pop to operands, create an infix expression of the three and
push the expression as an operand.
In the end when the stack has only one element left and the traversing is done, pop the top of
stack, it is the infix conversion.
Postfix Expression Evaluation
A postfix expression is a collection of operators and operands in which the operator is placed
after the operands. That means, in a postfix expression the operator follows the operands.
Postfix Expression has following general structure...
Operand1 Operand2 Operator
Example
Postfix Expression Evaluation using Stack Data Structure
A postfix expression can be evaluated using the Stack data
structure. To evaluate a postfix expression using Stack data
structure we can use the following steps...
1. Read all the symbols one by one from left to right in
the given Postfix Expression
2. If the reading symbol is operand, then push it on to
the Stack.
3. If the reading symbol is operator (+ , - , * , / etc.,),
then perform TWO pop operations and store the two
popped oparands in two different variables
(operand1 and operand2). Then perform reading
symbol operation using operand1 and operand2 and
push result back on to the Stack.
4. Finally! perform a pop operation and display the
popped value as final result.
Evaluation of Prefix Expressions
Prefix and Postfix expressions can be evaluated faster than an infix
expression. This is because we don’t need to process any brackets or
follow operator precedence rule. In postfix and prefix expressions
which ever operator comes before will be evaluated first,
irrespective of its priority. Also, there are no brackets in these
expressions. As long as we can guarantee that a valid prefix or
postfix expression is used, it can be evaluated with correctness.
We can convert infix to postfix and can convert infix to prefix.
Algorithm
EVALUATE_PREFIX(STRING)
Step 1: Put a pointer P at the end of the end
Step 2: If character at P is an operand push it to Stack
Step 3: If the character at P is an operator pop two
elements from the Stack. Operate on these elements
according to the operator, and push the result
back to the Stack
Step 4: Decrement P by 1 and go to Step 2 as long as there
are characters left to be scanned in the expression.
Step 5: The Result is stored at the top of the Stack,
return it
Step 6: End
Expression: +9*26
Character | Stack | Explanation
Scanned | (Front to |
| Back) |
-------------------------------------------
6 6 6 is an operand,
push to Stack
2 62 2 is an operand,
push to Stack
* 12 (6*2) * is an operator,
pop 6 and 2, multiply
them and push result
to Stack
9 12 9 9 is an operand, push
to Stack
+ 21 (12+9) + is an operator, pop
12 and 9 add them and
push result to Stack
Result: 21
Int st[5],top=-1;
0 1 2 3 4
10 22 33 44
Stack Using Linked List
The major problem with the stack implemented using an array is, it works only for a fixed
number of data values. That means the amount of data must be specified at the beginning of the
implementation itself. Stack implemented using an array is not suitable, when we don't know the
size of data which we are going to use. A stack data structure can be implemented by using a
linked list data structure. The stack implemented using linked list can work for an unlimited
number of values. That means, stack implemented using linked list works for the variable size of
data. So, there is no need to fix the size at the beginning of the implementation. The Stack
implemented using linked list can organize as many data values as we want.
In linked list implementation of a stack, every new element is inserted as
'top' element. That means every newly inserted element is pointed by
'top'. Whenever we want to remove an element from the stack, simply
remove the node which is pointed by 'top' by moving 'top' to its previous
node in the list. The next field of the first element must be
always NULL.
Example
In the above example, the last inserted node is 99 and the first inserted node is 25. The order of
elements inserted is 25, 32,50 and 99.
Stack Operations using Linked List
To implement a stack using a linked list, we need to set the
following things before implementing actual operations.
● Step 1 - Include all the header files which are used in the
program. And declare all the user defined functions.
● Step 2 - Define a 'Node' structure with two
members data and next.
● Step 3 - Define a Node pointer 'top' and set it to NULL.
● Step 4 - Implement the main method by displaying Menu
with list of operations and make suitable function calls in
the main method.
push(value) - Inserting an element into the Stack
We can use the following steps to insert a new node into the stack...
● Step 1 - Create a newNode with given value.
● Step 2 - Check whether stack is Empty (top == NULL)
● Step 3 - If it is Empty, then set newNode → next = NULL.
● Step 4 - If it is Not Empty, then set newNode →
next = top.
● Step 5 - Finally, set top = newNode.
Top
top = newNode
Top->next=newnode
pop() - Deleting an Element from a Stack
We can use the following steps to delete a node from the stack...
● Step 1 - Check whether stack is Empty (top == NULL).
● Step 2 - If it is Empty, then display "Stack is Empty!!!
Deletion is not possible!!!" and terminate the function
● Step 3 - If it is Not Empty, then define a Node pointer
'temp' and set it to 'top'.
● Step 4 - Then set 'top = top → next'.
● Step 5 - Finally, delete 'temp'. (free(temp)).
display() - Displaying stack of elements
We can use the following steps to display the elements (nodes) of a
stack...
● Step 1 - Check whether stack is Empty (top == NULL).
● Step 2 - If it is Empty, then display 'Stack is Empty!!!' and
terminate the function.
● Step 3 - If it is Not Empty, then define a Node
pointer 'temp' and initialize with top.
● Step 4 - Display 'temp → data --->' and move it to the next
node. Repeat the same until temp reaches to the first node in
the stack. (temp → next != NULL).
● Step 5 - Finally! Display 'temp → data ---> NULL'.
#include<stdio.h>
#include<conio.h>
struct Node
int data;
struct Node *next;
}*top = NULL;
void push(int);
void pop();
void display();
void main()
int choice, value;
clrscr();
printf("\n:: Stack using Linked List ::\n");
while(1){
printf("\n****** MENU ******\n");
printf("1. Push\n2. Pop\n3. Display\n4. Exit\n");
printf("Enter your choice: ");
scanf("%d",&choice);
switch(choice){
case 1: printf("Enter the value to be insert: ");
scanf("%d", &value);
push(value);
break;
case 2: pop(); break;
case 3: display(); break;
case 4: exit(0);
default: printf("\nWrong selection!!! Please try again!!!\n");
void push(int value)
struct Node *newNode;
newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = value;
if(top == NULL)
newNode->next = NULL;
else
newNode->next = top;
top = newNode;
printf("\nInsertion is Success!!!\n");
}
void pop()
if(top == NULL)
printf("\nStack is Empty!!!\n");
else{
struct Node *temp = top;
printf("\nDeleted element: %d", temp->data);
top = temp->next;
free(temp);
void display()
if(top == NULL)
printf("\nStack is Empty!!!\n");
else{
struct Node *temp = top;
while(temp->next != NULL){
printf("%d--->",temp->data);
temp = temp -> next;
printf("%d--->NULL",temp->data);
}
}
Recursion Basics
Some computer programming languages allow a module or function
to call itself. This technique is known as recursion. In recursion, a
function α either calls itself directly or calls a function β that in turn
calls the original function α. The function α is called recursive
function.
Example − a function calling itself.
int function(int value)
{
if(value < 1)
return;
function(value - 1);
printf("%d ",value);
}
Example − a function that calls another function
which in turn calls it again.
int function1(int value1) {// fun1 defination
if(value1 < 1)
return;
function2(value1 - 1); //fun2 call
printf("%d ",value1);
}
int function2(int value2) { fun2 defination
function1(value2); //fun1 call
}
Implementation
Many programming languages implement recursion by means
of stacks. Generally, whenever a function (caller) calls another
function (callee) or itself as callee, the caller function transfers
execution control to the callee. This transfer process may also
involve some data to be passed from the caller to the callee.
This implies, the caller function has to suspend its execution
temporarily and resume later when the execution control returns
from the callee function. Here, the caller function needs to start
exactly from the point of execution where it puts itself on hold. It
also needs the exact same data values it was working on. For this
purpose, an activation record (or stack frame) is created for the
caller function.
Int fun()
{
Int fun1();
}
Fun1()
{
Fun2();
}
Int fun2()
{
}
This activation record keeps the information about local variables, formal parameters,
return address and all information passed to the caller function.
Direct Recursion#
If a function calls itself, it’s known as direct recursion. This results in a
one-step recursive call: the function makes a recursive call inside its own
function body.
void directRecursionFunction()
// some code...
directRecursionFunction();
// some code...
}
int function(int value)
{
if(value < 1)
return;
function(value - 1);
printf("%d ",value);
}
Int add()
Add();
Below is an example of a direct recursive function that computes the square
of a number:
#include <iostream>
using namespace std;
// recursive function to calculate square of a number
int square(int x)
// base case
if (x == 0)
return x;
// recursive case
else
return square(x-1) + (2*x) - 1;
int main() {
// implementation of square function
int input=30;
cout << input<<"^2 = "<<square(input);
return 0;
Indirect Recursion#
If the function f1 calls another function f2 and f2 calls f1 then it is indirect
recursion (or mutual recursion).
This is a two-step recursive call: the function calls another function to make
a recursive call.
void indirectRecursionFunctionf1(); // defined fun
void indirectRecursionFunctionf2();// defined fun
void indirectRecursionFunctionf1() // Fun defination
// some code...
indirectRecursionFunctionf2(); //call fun
// some code...
}
void indirectRecursionFunctionf2()// Fun defination
// some code...
indirectRecursionFunctionf1(); //call fun
// some code...
Fun1()
Fun2();
Fun2()
Fun1();
Tail Recursion
Here we will see what is tail recursion. The tail recursion is basically
using the recursive function as the last statement of the function. So
when nothing is left to do after coming back from the recursive call,
that is called tail recursion. We will see one example of tail
recursion.
#include <iostream>
using namespace std;
void printN(int n){
if(n < 0){
return;
cout << n << " ";10 9 8 7 6 5 4 3 2 1 0
printN(n - 1);
int main() {
printN(10);
}
Output
10 9 8 7 6 5 4 3 2 1 0
Recursion tree
Tree Recursion is just a phrase to describe when you make a recursive call more
than once in your recursive case.
Backtracking | Introduction
The Backtracking is an algorithmic-method to solve a problem with an additional way.
It uses a recursive approach to explain the problems. We can say that the backtracking
is needed to find all possible combination to solve an optimization problem.
Backtracking is a systematic way of trying out different sequences of decisions until we
find one that "works."
Backtracking is a technique based on algorithm to solve problem. It uses recursive
calling to find the solution by building a solution step by step increasing values with
time. It removes the solutions that doesn't give rise to the solution of the problem
based on the constraints given to solve the problem.
Backtracking algorithm is applied to some specific types of problems,
● Decision problem used to find a feasible solution of the problem.
● Optimisation problem used to find the best solution that can be applied.
● Enumeration problem used to find the set of all feasible solutions of the
problem.
In backtracking problem, the algorithm tries to find a sequence path to the solution
which has some small checkpoints from where the problem can backtrack if no
feasible solution is found for the problem.
Example,
Here,
Green is the start point, blue is the intermediate point, red are points with no feasible
solution, dark green is end solution.
Here, when the algorithm propagates to an end to check if it is a solution or not, if it
is then returns the solution otherwise backtracks to the point one step behind it to
find track to the next point to find solution.
Algorithm
Step 1 − if current_position is goal, return success
Step 2 − else,
Step 3 − if current_position is an end point, return failed.
Step 4 − else, if current_position is not end point, explore and
repeat above steps.
Let’s use this backtracking problem to find the solution to N-Queen Problem.
In N-Queen problem, we are given an NxN chessboard and we have to place n queens
on the board in such a way that no two queens attack each other. A queen will attack
another queen if it is placed in horizontal, vertical or diagonal points in its way. Here,
we will do 4-Queen problem.
Here, the solution is −
Here, the binary output for n queen problem with 1’s as queens to the positions are
placed.
{0 , 1 , 0 , 0}
{0 , 0 , 0 , 1}
{1 , 0 , 0 , 0}
{0 , 0 , 1 , 0}