0% found this document useful (0 votes)
8 views58 pages

Application of Stack and Queue

The document discusses the implementation and applications of stacks and queues, particularly focusing on multiple stacks within a single array to optimize memory usage. It covers various applications of stacks, including string reversal, expression validation, and conversion between infix, prefix, and postfix notations. Additionally, it provides code examples for stack operations and algorithms related to these applications.

Uploaded by

Rudraksh Mall
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views58 pages

Application of Stack and Queue

The document discusses the implementation and applications of stacks and queues, particularly focusing on multiple stacks within a single array to optimize memory usage. It covers various applications of stacks, including string reversal, expression validation, and conversion between infix, prefix, and postfix notations. Additionally, it provides code examples for stack operations and algorithms related to these applications.

Uploaded by

Rudraksh Mall
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 58

Data Structures

Applications of Stack and Queue

Dr Deepak Gupta
Assistant Professor, SMIEEE
CSED, MNNIT Allahabad, Prayagraj
Email: deepakg@mnnit.ac.in
Multiple Stack
When we implemented a stack using an array, we had seen that the size of
the array must be known in advance. If the stack is allocated less space, then
frequent OVERFLOW conditions will be encountered.

In case, we allocate a large amount of space for the stack, it will result in
sheer wastage of memory. Thus, there lies a tradeoff between the frequency
of overflows and the space allocated.

So a better solution to deal with this problem is to have multiple stacks or to


have more than one stack in the same array of sufficient size.

0 1 2 3 4 ………………………………. n-4 n-3 n-2 n-1

Stack A Stack B
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 i.e. right to left.

#define MAX 50
int stack[MAX];
int topA = -1;
int topB = MAX;
#include <stdio.h>
#include <malloc.h>
#define MAX 10
int stack[MAX], topA = -1, topB = MAX;
int main()
{ case 5:
int option, val; printf("\n The contents of Stack A are :\n");
do display_stackA();
{ break;
printf("\n -----Menu----- "); case 6:
printf("\n 1. PUSH a element into Stack A"); printf("\n The contents of Stack B are :\n");
printf("\n 2. PUSH a element into Stack B"); display_stackB();
printf("\n 3. POP a element from Stack A"); break;
printf("\n 4. POP a element from Stack B"); }
printf("\n 5. Display the Stack A"); }while(option != 7);
printf("\n 6. Display the Stack B"); return 0;
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;
void pushA(int val) void pushB(int val)
{ {
if(topA == topB-1) if(topB-1 == topA)
printf("\n Overflow"); printf("\n Overflow");
else else
{ {
topA+=1; topB-=1;
stack[topA] = val; stack[topB] = val;
} }
} }

int popA() int popB()


{ {
int val; int val;
if(topA == -1) if(topB == MAX)
{ {
printf("\n Underflow"); printf("\n Underflow");
val = -999; val = -999;
} }
else else
{ {
val = stack[topA]; val = stack[topB];
topA--; topB++;
} }
return val; return val;
} }

void display_stackA() void display_stackB()


{ {
int i; int i;
if(topA == -1) if(topB == MAX)
printf("\n Stack A is empty"); printf("\n Stack B is Empty");
else else
{ {
for(i = topA; i >= 0; i--) for(i = topB; i < MAX;i++)
printf("\t %d", stack[i]); printf("\t %d",stack[i]);
} }
} }
Applications of Stacks

• Reversal of string or list

• Function calls

• Recursion

• Checking the validity of an expression containing nested parentheses

• Conversion of an infix expression into a postfix expression

• Evaluation of a postfix expression

• Conversion of an infix expression into a prefix expression

• Evaluation of a postfix expression

• Tower of Hanoi
Reversal of string
We can reverse a string by pushing each character of the string on the stack.
After the whole string is pushed on the stack, we can start popping the
characters from the stack and get the reversed string.

We have pushed the string “SPOT” on the stack and we get the reversed
string “TOPS”.

T O P S

T
O O O
P P P P P
S S S S S S S
Program of reversing a string using stack
#include<studio.h> void push(int item)
#include< string.h> {
#include<stdlib.h> if(isFull())
{
#define MAX 20
printf(“stack overflow”);
int top = -1;
return;
char stack[MAX]; }
char pop( ); top = top + 1;
void push (char); stack_arr[top] = item;
main() }
{ char str(20);
unsigned int i; char pop( )
printf(“Enter the string”); {
gets(str); int item;
for(i =0; i<starlen(str); i++) if(top = = -1)
push(str(i); {
for(i =0; i<starlen(str); i++) printf(“stack underflow”);
str[i] = pop(); return;
printf(“Reversed string is: ”); }
puts(str); item = stack_arr(top);
} top = top-1;
return item;
}
Checking the validity of an expression containing nested parentheses

• We can use stack to check the validity of an expression that uses nested
parentheses.
• An expression will be valid if it satisfies these two conditions:
– The total number of left parentheses should be equal to the total number of
right parentheses in the expression.
– For every right parentheses there should be a left parentheses of the same type.

• [A-B*(C+D)) Invalid
• (1+5} Invalid
• [5+4*(9-2)] Valid
• [A/(B+C)*D] Valid
Procedure:
1. Initially take an empty stack.
2. Scan the symbols of expression from left to right
3. If a symbol is a left parenthesis then push it on the stack
4. If a symbol is a right parenthesis
if the stack is empty
Invalid: right parentheses are more than left parenthesis
else
pop an element from the stack.
if the popped parenthesis does not match the parentheses being scanned.
Invalid: Mismatched parenthesis.
5. After scanning all the symbols
If the stack is empty
Valid: Balanced parenthesis
else
invalid: left parentheses more than right parentheses.
[A/(B-C)*D] [A/(B-C)*D] [A/(B-C)*D] [A/(B-C)*D]
Symbol Stack Symbol Stack Symbol Stack Symbol Stack

[ A / (

(
[ [ [ [

[A/(B-C)*D] [A/(B-C)*D] [A/(B-C)*D] [A/(B-C)*D]


Symbol Stack Symbol Stack Symbol Stack Symbol Stack

B A- C )

( ( (
[ [ [ [

[A/(B-C)*D] [A/(B-C)*D] [A/(B-C)*D]


Symbol Stack Symbol Stack Symbol Stack

* D ]

[ [
#include <stdio.h> int check(char exp[ ])
#define MAX 30 {
int stack[MAX], top = -1; int I;
void push(char); char temp;
char pop(); for(i=0; i<strlen(exp); i++)
int match(char a, char b); {
main() if(exp[i] ==‘(‘ || exp[i] ==‘{‘ || exp[i] == ‘[‘)
{ push(exp[i]);
int valid; if(exp[i] ==‘)‘ || exp[i] ==‘}‘ || exp[i] == ‘]‘)
char exp[MAX]; if(top = = -1)
printf(“Enter an algebraic expression); {
gets(exp); printf(“Right parentheses are more than left\n)”
valid = check(exp); return 0;
if(valid = = 1) }
printf(“Valid expression”); else
else {
printf(“Invalid expression”); temp = pop( );
} if(!match(temp, exp[i]))
{
printf(“Mismatched parentheses are :”);
printf(“%c and %c\n”, temp, exp[i]);
return 0;
int match(char a, char b) }
{ }
if(a ==‘[‘ && b == ‘]’) }
return 1; if(top = -1)
if(a ==‘{‘ && b == ‘}’) {
return 1; printf(“Balanced Parentheses\n”);
if(a ==‘(‘ && b == ‘)’) return 1;
return 1; }
return 0; else
} {
printf(“left parentheses are more than right parentheses\n”);
return 0;
}
}
Notation
The way to write arithmetic expression is known as a notation.

An arithmetic expression can be written in three different but


equivalent notations
1. Infix Notation
2. Prefix (Polish) Notation
3. Postfix (Reverse-Polish) Notation

Infix Notation: The conventional method of representing an arithmetic


expression is known as infix because the operator is placed in between the
operands. eg. A+B
Prefix Notation: If the operator is placed before the operands then this
notation is called Prefix of polish notations. eg. +AB
Postfix Notation: If the operator is placed after the operands then this
notation is called Prefix of polish notations. Eg. AB+
Evaluation of a Postfix Expression

1. Add a ) at the end of the postfix expression

2. Scan every character of the postfix expression and repeat Steps 3 and 4
until ) is encountered

3. If an operand is encountered, out it on the STACK.

4. If an operator O is encountered, then


1. POP the two top elements of STACK as A(topmost element) and
B(next-to-top element).
2. Evaluate B O A.
3. Push the result of evaluation on the STACK.

5. SET RESULT equal to the topmost element of the STACK.


Given postfix expression: 456*+
Consider the following postfix notation 8 2 3 * 8 + 2 / –. The equivalent infix
expression is 8 – ((2 * 3) + 8) / 2

The final number in the stack, 1, is the value of the postfix expression.
Evaluation of a Prefix Expression
Consider the following prefix notation: /+33-+47*+123.
First reverse the prefix expression is 321+*74+-33+/
Infix expression to a Postfix expression
1. Scan the infix expression from left to right.
2. If the scanned character is an operand,
put it in the postfix expression.
3. If the scanned character is a ‘(‘,
push it to the stack.
4. If the scanned character is a ‘)’,
pop the stack and output it until a ‘(‘ is encountered, and discard both the
parenthesis.
5. If the scanned character is an operator,
(a) pop the operators that have precedence greater than or equal to the precedence
of the symbol operator, and add these popped operators to the array postfix.
(b) Push the scanned symbol operator on the stack. (Assume that left parenthesis
has the least precedence).
6. After all the symbols of array infix have been scanned, pop all the operators remaining
on the stack and add them to the array postfix.
S. No. Operator Description Associativity
1 () Parentheses Left to right
2 [] Brackets Left to right
3 . Object Left to right
4 -> Pointer Left to right
5 ++ — Postfix increment and decrement Left to right
6 ++ — Prefix increment and decrement Right to left
7 – Unary plus/minus Right to left
8 !~ Logical negation and bitwise complement Right to left
9 (type) Cast Right to left
10 * Dereference operator Right to left
11 & Address of operator Right to left
12 sizeof Unary operator, returns size in bytes. Right to left
13 */% Multiplication/ division/ modulus Left to right
14 +,– Addition/ Subtraction Left to right
15 << >> Bitwise left shift/ Bitwise right shift Left to right
16 < <= Relation less than, less than or equal to Left to right
17 > >= Relational greater than, greater than or equal to Left to right
18 == != Is equal to, Not equal to Left to right
19 & Bitwise AND Left to right
20 ^ Bitwise exclusive OR Left to right
21 | Bitwise inclusive OR Left to right
22 && Logical AND Left to right
23 || Logical OR Left to right
24 ?: Ternary operator Left to right
25 = Assignment operator Right to left
26 += -= Addition/Subtraction assignment Right to left
27 *= /= Multiplication/division assignment Right to left
28 %= &= Modulus/Bitwise AND assignment Right to left
29 ^= |= Bitwise exclusive/ Bitwise inclusive OR Right to left
30 <<= >>= Bitwise left shift/ Bitwise right shift assignment Right to left
31 , Comma operator Left to right
Infix to postfix conversion
stackVect

infixVect
(A+(B*C-(D/E ^ F) *G)*H)

postfixVect
Infix to postfix conversion
stackVect

infixVect
A+(B*C-(D/E ^ F) *G)*H)

postfixVect

(
Infix to postfix conversion
stackVect

infixVect
+(B*C-(D/E ^ F) *G)*H)

postfixVect
A

(
Infix to postfix conversion
stackVect

infixVect
(B*C-(D/E ^ F) *G)*H)

postfixVect
A
+
(
Infix to postfix conversion
stackVect

infixVect
B*C-(D/E ^ F) *G)*H)

postfixVect

( A
+
(
Infix to postfix conversion
stackVect

infixVect
*C-(D/E ^ F) *G)*H)

postfixVect

( AB
+
(
Infix to postfix conversion
stackVect

infixVect
C-(D/E ^ F) *G)*H)

postfixVect
*
( AB
+
(
Infix to postfix conversion
stackVect

infixVect
-(D/E ^ F) *G)*H)

postfixVect
*
( ABC
+
(
Infix to postfix conversion
stackVect

infixVect
(D/E ^ F) *G)*H)

postfixVect
-
( ABC*
+
(
Infix to postfix conversion
stackVect

infixVect
D/E ^ F) *G)*H)
(
postfixVect
-
( ABC*
+
(
Infix to postfix conversion
stackVect

infixVect
/E ^ F) *G)*H)
(
postfixVect
-
( ABC*D
+
(
Infix to postfix conversion
stackVect

infixVect
/ E ^ F) *G)*H)
(
postfixVect
-
( ABC*D
+
(
Infix to postfix conversion
stackVect

infixVect
/ ^ F) *G)*H)
(
postfixVect
-
( ABC*DE
+
(
Infix to postfix conversion
stackVect
^ infixVect
/ F) *G)*H)
(
postfixVect
-
( ABC*DE
+
(
Infix to postfix conversion
stackVect
^ infixVect
/ ) *G)*H)
(
postfixVect
-
( ABC*DEF
+
(
Infix to postfix conversion
stackVect

infixVect
*G)*H)

postfixVect
-
( ABC*DEF^/
+
(
Infix to postfix conversion
stackVect

infixVect
G)*H)
*
postfixVect
-
( ABC*DEF^/
+
(
Infix to postfix conversion
stackVect

infixVect
)*H)
*
postfixVect
-
( ABC*DEF^/G
+
(
Infix to postfix conversion
stackVect

infixVect
*H)

postfixVect
ABC*DEF^/G*-
+
(
Infix to postfix conversion
stackVect

infixVect
H)

postfixVect

* ABC*DEF^/G*-
+
(
Infix to postfix conversion
stackVect

infixVect
)

postfixVect

* ABC*DEF^/G*-H
+
(
Infix to postfix conversion
stackVect

infixVect

postfixVect
ABC*DEF^/G*-H*+
Consider the following expression:
A+(B*C/D-E^F^I+G)/H
Its postfix will be:
Input symbol Stack Postfix
A Empty A
+ + A
( +( A
B +( AB
* +(* AB
C +(* ABC
/ +(/ ABC*
D +(/ ABC*D
– +(- ABC*D/
E +(- ABC*D/E
^ +(-^ ABC*D/E
F +(-^ ABC*D/EF
^ +(-^ ABC*D/EF^
I +(-^ ABC*D/EF^I
+ +(+ ABC*D/EF^I^-
G +(+ ABC*D/EF^I^-G
) + ABC*D/EF^I^-G+
/ +/ ABC*D/EF^I^-G+
H +/ ABC*D/EF^I^-G+H
NULL Empty ABC*D/EF^I^-G+H/+

Thus, the outcome of the above expression in postfix is: ABC*D/EF^I^-G+H/+


Infix expression to Prefix expression

To convert an infix expression to a prefix expression, we can use the stack data
structure. The idea is as follows:

Step 1: Reverse the infix expression. Note while reversing each ‘(‘ will become
‘)’ and each ‘)’ becomes ‘(‘.

Step 2: Convert the reversed infix expression to “nearly” postfix expression.


While converting to postfix expression, instead of using pop operation to pop
operators with greater than or equal precedence, here we will only pop the
operators from stack that have greater precedence.

Step 3: Reverse the postfix expression.

The stack is used to convert infix expression to postfix form.


Example: Convert (A + B) * C - D / E to Prefix
Step 1: Reverse the infix expression
Original:
(A+B)∗C−D/E
Reversed (swap ( and ) as well):
E/D−C∗(B+A)

Step 2: Convert the reversed expression to Postfix


ED/CBA+*-

Step 3: Reverse the postfix to get prefix


Reverse ED/CBA+*-:
−∗C+BA/DE

So, the Prefix Expression is:


−∗C+BA/DE
Recursion

The process in which a function calls itself directly or indirectly is called


recursion.
In recursion, a function either calls itself directly or calls another function
which called the previous function.

Need of Recursion:
Recursion is an amazing technique with the help of which we can reduce the
length of our code and make it easier to read and write.

Properties of Recursion:
• Performing the same operations multiple times with different inputs.
• In every step, we try smaller inputs to make the problem smaller.
• Base condition is needed to stop the recursion otherwise infinite loop will
occur
Types of Recursion
• Any recursive function can be characterized based on:

▪ whether the function calls itself directly or indirectly (direct or


indirect recursion).

▪ whether any operation is pending at each recursive call (tail-


recursive or not).

▪ the structure of the calling pattern (linear or tree-recursive).

Recursion

Direct Indirect Linear Tree Tail


Direct and Indirect Recursion
Direct Recursion: If a function f1() is called
inside its own function body, then that
recursion is called direct recursion.
int fib(int n)
{
if(n ==0 || n==1)
return 1;
return (fib(n-1)+fib(n-2));
} f1()
{

Indirect Recursion: If a function f1() calls f2() f2();
and the function f2() in turn calls f1(), then this is …
}
indirect recursion.
f2()
{

f1();

}
linear or tree-recursive
Linear Recursion: In simple words, a recursive function is said to be
linearly recursive when no pending operation involves another recursive
call to the function.
For example, the factorial function is linearly recursive as the pending
operation involves only multiplication to be performed and does not
involve another call to fact( ) function.
int fact(int n)
{
if(n ==0)
return 1;
return (n*fact(n-1)); /* Linear recursion
}
linear or tree-recursive
Tree Recursion: A recursive function is said to be tree recursive (or non-
linearly recursive) if the pending operation makes another recursive call to
the function.
For example, the Fibonacci function Fib in which the pending operations
recursively calls the Fib function.

int fib(int n)
{
if(n ==0 || n==1)
return 1;
return (fib(n-1)+fib(n-2));
}
Tail Recursion
1. In void function, a recursive function is called tail recursion if it is the
last statement to be executed inside the function.
void display1(int n)
{
if(n ==0)
return;
printf(“%d”,n);
display1(n-1); /* Tail recursive call
}

void display2(int n)
{
if(n ==0)
return;
display2(n-1); /* Not a Tail recursive call
printf(“%d”,n);
}
2. In a non void function, if the recursive call appears in the return statement
and that call is not part of an expression then the call is tail recursive.

int GCD(int a, int b)


{
if(b ==0)
return a;
return GCD(b, a%b); /* Tail recursive call
}

int fact(int n)
{
if(n ==0)
return 1;
return (n*fact(n-1)); /* Not a Tail recursive call
}
Tower of Hanoi

Tower of Hanoi is a mathematical puzzle where we have three rods (A, B,


and C) and N disks. Initially, all the disks are stacked in decreasing value of
diameter i.e., the smallest disk is placed on the top and they are on rod A.
The objective of the puzzle is to move the entire stack to another rod (here
considered C), obeying the following simple rules:

➢ Only one disk can be moved at a time.


➢ Each move consists of taking the upper disk from one of the stacks and
placing it on top of another stack i.e. a disk can only be moved if it is the
uppermost disk on a stack.
➢ No disk may be placed on top of a smaller disk.
Move disk 1 from A to C (A->C)
Move disk 2 from A to B (A->B)
Move disk 1 from C to B (C->B)
Move disk 3 from A to C (A->C)
Move disk 1 from B to A (B->A)
Move disk 2 from B to C (B->C)
Move disk 1 from A to C (A->C)
General Solution:
Step 1 − Move upper n-1 disks from source (A) to aux (B) using destination
(C) as a temporary pillar

Step 2 − Move nth disk from source(A) to destination (C)

Step 3 − Move n-1 disks from aux(B) to destination (C) using source (A) as
the temporary pillar.
void tofh(int ndisk, char source, char temp, char dest)
{
if(ndisk == 1)
{
printf(“Move Disk %d from %c→%c\n”, ndisk, source, dest);
return;
}
tofh(ndisk-1, source,dest,temp);
printf(“Move Disk %d from %c→%c\n”, ndisk, source, dest);
tofh(ndisk-1, temp,source,dest);
}

Recursive Equation : T(n) = 2T(n-1) + 1

T(n)= O( 2n - 1), or you can say O(2n) which is exponential.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy