0% found this document useful (0 votes)
13 views

2.1 Stack-1

Uploaded by

abc
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

2.1 Stack-1

Uploaded by

abc
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 81

STACK

Syllabus
Stacks: Abstract Data Type, Primitive Stack
operations: Push & Pop, Array and Linked
Implementation of Stack in C, Application of
stack: Prefix and Postfix Expressions,
Evaluation of postfix expression, Iteration and
Recursion- Principles of recursion, Tail
recursion, Removal of recursion Problem
solving using iteration and recursion with
examples such as binary search, Fibonacci
numbers, and Hanoi towers. Tradeoffs between
iteration and recursion.
Introduction
A stack is a data structure in which addition of
new element or deletion of an existing element
always takes place at the same end. This end is
often known as top of stack.
When an item is added to a stack, the operation
is called push, and when an item is removed
from the stack the operation is called pop. Stack
is also called as Last- In-First- Out (LIFO) list.
A helpful analogy is to think of a stack of books;
you can remove only the top book, also you can
add a new book on the top.
Stack (ADT)
Stack is an Abstract data structure (ADT) works on the
principle Last in First out (LIFO). The last element add to
the stack is the first element to be delete. Insertion and
deletion can be takes place at one end called TOP. It looks
like one side closed tube.
The add operation of the stack is called push operation
The delete operation is called as pop operation.
Push operation on a full stack causes stack overflow.
Pop operation on an empty stack causes stack underflow.
TOP is a pointer, which is used to access the top element
of the stack.
If you push elements that will be added at the top of the
stack.
In the same way when we pop the elements, the element
at the top of the stack is deleted.
Operations on Stack
There are various operations which can be
performed on stack.
Push : Adding an element onto the stack
Pop : Removing an element from the stack
peek() − get the top data element of the
stack, without removing it.
isFull() − check if stack is full.
isEmpty() − check if stack is empty.
Implementation of STACK in memory

There are two ways to implement a stack in


memory:
Array implementation
Linked-list implementation

https://www.cs.usfca.edu/~galles/visualization/
Algorithms.html
Array implementation of Stack

Value of TOP Status of STACK

-1 Empty [Underflow]

0 Only one element in the stack

N-1 or MAX-1 Stack is full [Overflow]


Algorithm
PUSH [STACK, TOP, MAX, ITEM]
Step-1: If TOP==MAX-1 then
Print “Overflow”
Return
Step-2: TOP=TOP+1
Step-3: STACK[TOP]=ITEM
Step-4: Exit
Algorithm
POP [STACK, TOP, ITEM]
Step-1: If TOP== -1 then
Print “Underflow”
Return
Step-2: ITEM= STACK[TOP]
Step-3: TOP=TOP-1
Step-4: Exit
Algorithm
PEEK [STACK, TOP, ITEM]
Step-1: If TOP== -1 then
Print “Underflow”
Return
Step-2: Return STACK[TOP]
Step-3: Exit
Algorithm
IS_FULL [STACK, TOP, ITEM]
Step-1: If TOP== Max-1 then
Print “Stack is Full”
Return “True”
Step-2 : else Return “False”
Step-3: Exit
Algorithm
IS_EMPTY [STACK, TOP, ITEM]
Step-1: If TOP=-1 then
Print “Stack is Empty”
Return “True”
Step-2: else Return “False”
Step-3 : Exit
Implementation of Stack using Linked
List
Stacks can be easily implemented using a linked list.
Stack is a data structure to which a data can be
added using the push() method and data can be
removed from it using the pop() method.
With Linked list, the push() operation can be
replaced by the insert_at_front() method of linked
list which insert a new node at the front of the
linked-list
Pop() operation can be replaced by a function
delete_front() which deletes the front node of the
linked list.
In this way our Linked list will virtually become a
Stack with push() and pop() methods.
Inserting an element into the
Stack
We can use the following steps to insert a new
node into the stack:
* TOP is pointing to the first node of the linked
list.
Step 1 - Create a newNode with given value.
Step 2 - Check whether stack
is Empty (TOP == NULL)
a - If it is Empty, then set newNode →
next = NULL.
Step 3 - If it is Not Empty, then set newNode →
next = TOP.
Step 4 - Set TOP = newNode.
Deleting an Element from a Stack
* TOP is pointing to the first node of the linked
list.

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 temp=TOP.
Step 4 - Then set TOP = TOP → next.
Displaying elements of stack
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'.
Applications of stack
Stacks can be used for expression evaluation.
Stacks can be used to check balanced
parenthesis in an expression.
Stacks can be used for Conversion from Infix
to Post-fix form.
Stacks can be used for process management.
Stack data structures are used in backtracking
problems.
Stacks are used in depth-first-search (DFS)
GATE-CS-2006
Following is C like pseudo code of a function that takes a number as
an argument, and uses a stack S to do processing.
void fun(int n)
{
Stack S; // Say it creates an empty stack S
while (n > 0)
{
// This line pushes the value of n%2 to stack S
push(&S, n%2);

n = n/2; 1. Prints the value of logn


2. Prints binary representation of n in
}
reverse order
3. Prints binary representation of
// Run while Stack S is not empty n
while (!isEmpty(&S)) 4. Prints the value of logn in reverse
printf("%d ", pop(&S)); // pop an order
element from S and print it
}
ISRO CS 2017
 The best data structure to check whether an arithmetic
expression has balanced parenthesis is a:
Stack
Queue
List
Tree

 Which of the following permutation can be obtained in the


same order using a stack assuming that input is the
sequence 5, 6, 7, 8, 9 in that order?
7, 8, 9, 5, 6
5, 9, 6, 7, 8
7, 8, 9, 6, 5
9, 8, 7, 5, 6

Push 5 Push 6 Push 7 Pop 7 Push 8 Pop 8 Push 9 Pop 9 Pop 6


Pop 5
UGC NET CS 2017 Jan - II
The seven elements A, B, C, D, E, F and G are
pushed onto a stack in reverse order, i.e.,
starting from G. The stack is popped five
times and each element is inserted into a
queue.Two elements are deleted from the
queue and pushed back onto the stack. Now,
one element is popped from the stack. The
popped item is:
A
B
F
G
GATE CS 2021 | Set 1
 Consider the following sequence of operations on an
empty stack.
Push(54);push(52);pop();push(55);push(62);
s=pop();
 Consider the following sequence of operations on an
empty queue.
enqueue(21);enqueue(24);dequeue();enqueue(28);enque
ue(32);q=dequeue();
The value of s+q is:
86
68
24
94
Expressions
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 is a collection of operators and
operands that represents a specific value.
Based on the operator position, expressions are
divided into THREE (3) types. They are as
follows:
 Infix Expression
 Postfix Expression
 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
Infix: a + b * c
operands: a, b, c
operators: +, *
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
Infix: a + b
Prefix: + a b
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
Infix: a + b
Postfix: a b +
Infix to Postfix Conversion
To convert Infix Expression into Postfix Expression using a stack
data structure, we can use the following steps:
1. Push ‘(‘ on to the stack and add ‘)’ at the end on infix
expression.
2. Read all the symbols one by one from left to right in the
given Infix Expression.
3. If the reading symbol is operand, then directly print it to
the result.
4. If the reading symbol is left parenthesis '(', then Push it on
to the Stack.
5. If the reading symbol is right parenthesis ')', then Pop all
the contents of stack until the first left parenthesis is poped
and print each poped symbol to the result.
6. If the reading symbol is operator (+ , - , * , / etc.,) then pop
all the operators which have higher or equal precedence
than current operator and print them to the result. After
that Push the current operator on to the Stack.
Example
Consider the following Infix Expression: ( A +
B)*(C-D)
Evaluation of Postfix Expressions

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
GATE-CS-2004
Assume that the operators +, -, × are left
associative and ^ is right associative. The
order of precedence (from highest to lowest)
is ^, x , +, -. The postfix expression
corresponding to the infix expression a + b ×
c - d ^ e ^ f is:
a b c × + d e f ^ ^ -
a b c × + d e ^ f ^ -
a b + c × d - e ^ f ^
- + a × b c ^ ^ d e f
What is the output of the program for the
following input:
52*332+*+ [Gate IT 2007]
15
25
30
150

The result after evaluating the postfix expression:


10 5 + 60 6 / * 8 - [GATE-CS-2015 (Set 3)]
284
213
142
71
AKTU Questions
Write an algorithm for converting infix
expression into postfix expression. Trace your
algorithm for infix expression Q into its
equivalent postfix expression P, Q: A + ( B / C * D
^ E + F) * G * H [AKTU 2022]
Evaluate the following postfix expression using
stack. 2 3 9 * + 2 3 ^ - 6 2 / + , show the
contents of each and every steps. Also find the
equivalent prefix form of above expression.
Where ^ is an exponent operator. [AKTU
2020]
Iteration
Looping is when we want to run through the
same block of code a specific number of times,
or repeatedly until a condition is met.
Iteration refers to the process in which the
code segment is executed once. One iteration
refers to 1-time execution of a loop. A loop can
undergo many iterations.
int factorial( int N ) {
int product = 1;
for ( int j=1; j<=N; j++ )
product = product * j;
return product;
}
Recursion
In simple words, recursion is a problem solving
technique, and in some cases, a programming
technique that has a very special and exclusive
property.
In recursion, a function or method has the ability
of calling itself to solve the problem. The
process of recursion involves solving a problem
by turning it into smaller varieties of itself.
The process in which a function calls itself could
happen directly as well as indirectly. Some
of the problems that can be solved using
recursion include DFS of Graph, Towers of Hanoi,
different types of tree traversals, and others.
Factorial of a number using recursion

int factorial(int n)
{
if(n = = 0)
return 1;
else
return (n * factorial(n-1));
}
Generating nth Fibonacci
number
int fibo(int a, int b, int n)
{
if(n==1)
return a;
else if(n==2)
return b;
else
return fibo(b,a+b,n-1);
}
Types of recursion
Direct recursion is the simpler way as it only
involves a single step of calling the original
function. Direct recursion can be used to call just
a single function by itself.
Indirect recursion
 In indirect recursion, a function calls another
function which then calls the first function again. The
recursion ends when the base case is met, at this
point, the process stops.
 There is always a variation in the depth of indirect
recursion, and this variation in depth depends on the
number of functions involved in the recursion.
Example
void funA(int n)
{
if (n > 0) {
printf("%d ", n);
funB(n - 1);
}
}
void funB(int n)
{
if (n > 1) {
printf("%d ", n);
funA(n / 2);
}
}
int main() {
funA(20); }
Head Recursion
If a recursive function calling itself and that recursive call is the first
statement in the function then it’s known as Head
Recursion. There’s no statement, no operation before the call.
The function doesn’t have to process or perform any operation at
the time of calling and all operations are done at returning time.

void fun(int n)
{
if (n > 0) {
fun(n - 1);
printf("%d ", n);
}
}
int main()
{
int x = 3;
fun(x);
return 0;
}
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.

void FUN(int n){


if(n < 0){
return;
}
printf(“%d\n”, n);
FUN(n - 1);
}
int main() {
FUN(3);
}
Continued…
Tail recursion is important because it can be
implemented more efficiently than general recursion.
When we make a normal recursive call, we have to
push the return address onto the call stack then jump
to the called function. This means that we need a stack
whose size is linear in the depth of the recursive calls.
 When we have tail recursion we know that as soon as
we return from the recursive call we're going to
immediately return as well, so we can skip the entire
chain of recursive functions returning and return
straight to the original caller.
That means we don't need a stack at all for all of the
recursive calls, and can implement the final call as a
simple jump, which saves us space called Tail call
elimination method.
Linear Recursion
A function is called the linear recursive if the
function makes a single call to itself at each
time the function runs and grows linearly in
proportion to the size of the problem.
fun(n) {
if(n>0) {
fun(n-1); // Calling itself only once
}
}
Tree Recursion
To understand Tree Recursion let’s first understand Linear
Recursion. If a recursive function calling itself for one time then
it’s known as Linear Recursion. Otherwise if a recursive function
calling itself for more than one time then it’s known as Tree
Recursion.
void fun(int n)
{
if (n > 0) {
printf("%d ", n);
fun(n - 1);
fun(n - 1);
}
}
int main()
{
fun(3);
return 0;
}
Nested Recursion
In this recursion, a recursive function will pass the parameter as
a recursive call. That means “recursion inside recursion”.
int fun(int n)
{
if (n > 100)
return n - 10;
return fun(fun(n + 11));
}
int main()
{
int r;
r = fun(95);
printf("%d\n", r);
return 0;
}
Time and Space Complexities of Recursion

Types of Time Space


Recursion Complexity Complexity
Tail Recursion O(n) O(n) / O(1) By
using tail-call-
elimination method
Head Recursion O(n) O(n)

Tree Recursion O(2^n) O(n)

Nested Recursion O(n) O(n)


When is recursion used?
You should choose recursion if the problem
that you are going to solve is mentioned in
recursive terms and the recursive solution
seems less complex.
You should know that recursion, in most
cases, simplifies the implementation of the
algorithms that you want to use. Now if the
complexities associated with using iteration
and recursion are the same for a given
problem, you should go with iteration as the
chances of it being more efficient are higher.
Tradeoff between Iteration and Recursion
Problem solving using
iteration and recursion
Binary Search
Binary search is the search technique which works
efficiently on the sorted lists. Hence, in order to
search an element into some list by using binary
search technique, we must ensure that the list is
sorted.
Binary search follows divide and conquer
approach in which, the list is divided into two
halves and the item is compared with the middle
element of the list. If the match is found then, the
location of middle element is returned otherwise,
we search into either of the halves depending
upon the result produced through the match.
Binary search [Iterative approach]
int binarySearch(int low,int high,int key){
while(low<=high)
{
int mid=(low+high)/2;
if(a[mid]<key){
low=mid+1;
}
else if(a[mid]>key){
high=mid-1;
}
else{
return mid;
}
}
return -1; //key not found
}
Binary search [Recursive approach]
Fibonacci numbers
The Fibonacci sequence is one of the most
famous formulas in mathematics. Each
number in the sequence is the sum of the
two numbers that precede it. So, the
sequence goes: 1, 1, 2, 3, 5, 8, 13, 21, 34,
and so on.
The mathematical equation describing it
is Xn= Xn-1 + Xn-2
We observe that many of the natural things
follow the Fibonacci sequence. It appears in
biological settings such as branching in trees,
the arrangement of leaves on a stem, the
fruit sprouts of a pineapple, the flowering of
Fibobacci Series [Recursive approach]
int fibbonacci(int n) {
if(n == 0) {
return 0;
}
else if(n == 1) {
return 1;
}
else {
x = fibbonacci(n-1) + fibbonacci(n-2);
printf(“%d\t”, x);
return (x);
}
}
Tower of Hanoi
The Tower of Hanoi, is a mathematical
problem which consists of three rods and
multiple disks. Initially, all the disks are placed
on one rod, one over the other in descending
order of size similar to a cone-shaped tower.
The objective of this problem is to move the
stack of disks from the initial rod to another
rod, following these rules:
A disk cannot be placed on top of a smaller
disk
No disk can be placed on top of the smaller
disk.
The goal is to move all the disks from the
leftmost rod to the rightmost rod. To move N
disks from one rod to another, 2N−1 steps are
required. So, to move 3 disks from starting the
rod to the ending rod, a total of 7 steps are
required.
Disadvantages of Recursion
Recursion has several disadvantages, including:
• Memory usage: Recursion uses more memory than
iteration because each recursive call adds a new
frame to the call stack. If a recursive subprogram
has many parameters, or the parameters are
memory intensive, the recursive calls can use up all
the computer's memory and cause a system error.
• Slow running time: Recursion can be slow if it's
not used correctly with memoization.
• Confusing: Recursion can be confusing.
• Not always the best option: Recursion may not
be the best option for an algorithm. You may want to
avoid recursion if the problem doesn't have a clear
base case or a recursive case.
Removal of Recursion
Recursion can be removed by two ways:
Using Iteration (loop): Recursion can be removed
by replace the selection structure with a loop. If
some data need to be stored for processing after
the end of the recursive step, a data structure is
needed in addition to the loop. The data structure
vary from a simple string or an array to a stack.

Using Stack
GATE CS 2011
unsigned int fun(unsigned int n, unsigned int r)
{
if (n > 0) return (n%r + fun (n/r, r ));
else return 0;
}
What is the return value when it is called as
fun(345, 10) ?
345
12
5
3
GATE-CS-2015 (Set 2)
int fun (int n)
{
int x=1, k;
if (n==1) return x;
for (k=1; k < n; ++k)
x = x + fun(k) * fun(n – k);
return x;
}
The return value of fun(5) is:
1
 21
 51
 31
fun(5) = 1 + fun(1) * fun(4) + fun(2) * fun(3) + fun(3) * fun(2) + fun(4) *
fun(1)
= 1 + 2*[fun(1)*fun(4) + fun(2)*fun(3 )]
GATE-CS-2004
int f(int n)
{
static int i = 1;
if (n >= 5)
return n;
n = n+i;
i++;
return f(n);
}
The value returned by f(1) is:
5
6
7
8
GATE-CS-2016 (Set 1)
void count(int n) {
static int d=1;
printf(“%d”, n);
printf(“%d”, d);
d++;
if(n > 1) count(n-1);
printf(“%d”, d);
}
What will be the output of count(3)?
3 1 2 2 1 3 4 4 4
3 1 2 1 1 1 2 2 2
3 1 2 2 1 3 4
3 1 2 1 1 1 2

You might also like