Module 2 DSA Notes MUSE (1)
Module 2 DSA Notes MUSE (1)
Definition of Stack
It is and abstract data type commonly used in most of the programming language. A stack is a linear
data structure in which insertion and deletion of the elements are allowed only at one end called “top”
of the stack.
Stacks are also known as Last-In-First-Out (LIFO) or First In Last Out (FILO) list, Since the last
element inserted into a stack is the first element removed.
Stack operations
• push(): insert data onto the stack
• pop(): deletes the element present on the top of the stack.
• top() or peek(): returns the last inserted element without removing it.
• Size(): returns the size or number of elements in the stack.
• display(): display the contents of the stack.
• overflow or isFull(): check whether stack full or not.
• underflow or isEmpty(): check whether stack full or not.
Applications of Stack
• Reverse a string or word. Ex: radar radar
• Undo mechanism in Microsoft word. Ex: ctrl+z
• Function call: when you call function something or value would return.
• Recursion: chain function call i.e., function is calling itself again and again.
• To check the balance of the parenthesis. Ex: (), {}, [] for each opening there is proper closing.
• Infix, postfix, prefix etc.
• Topological sorting, DFS (Depth first search), Tower of Hanoi etc.
• Evaluation of postfix expression.
1
Data Structures and Applications, MUSE
Define 1-D array of specific size and insert/delete the values in the array by using LIFO principle with
the help of variable “top”.
#define N 5
int stack[N];
int top = -1;
push() or insert--- the two steps to push data onto the stack are,
• Check whether the following stack is full by comparing “top” with size “N” i.e., (top==N-1) if
it is full then display “overflow” condition and terminate.
• If it is not full, then increment the “top” and assign the value.
pop() or delete-- the two steps to pop data from the stack are,
• Check whether the stack is empty by comparing “top” with size “-1” i.e., (top==-1) if it is empty
then display “underflow” condition and terminate.
• If it is not empty, then decrement the “top” and return the value.
2
Data Structures and Applications, MUSE
• Check whether the stack is empty by comparing “top” with size “-1” i.e., (top==-1) if it is empty
then display stack is empty and terminate.
• If it is not empty, then run a for loop from the top till it reaches “0” by decrementing and print
contents.
#define N 1
int stack[N];
int *stack;
int top = -1;
Function to perform push operation in stack
void push()
{
if (top = = -1)
{
printf(“stack full\n”);
printf(“increase stack by 1\n”);
N++;
realloc(*stack, N, int);
}
else
{
top++;
stack[top] = x;
}
}
3
Data Structures and Applications, MUSE
Operands may be variables like a, b, c etc. or a constant like 5, 4, 3etc. operators is symbol which
signifies a mathematical or logical operations between operands such as +, -, *, ^, %, /.
• Infix: it is a form of arithmetic expression in which we fix the operators in between two
operands.
Example: (A+B)*(C-D)
• Prefix or Polish Notation: it is a form of arithmetic expression in which we fix the operators
before its two operands.
Example: +*CD ^EF+OP
• Postfix or Reverse Polish Notation: it is a form of arithmetic expression in which we fix the
operators after two operands. The postfix notation is also called as “Suffix notation”.
Example: AB*XY/ZF+
Example 1, Example 2,
=1+2*5+30/5 = 2^2^3
=1+10+30/5 = 2^8
=1+10+6 = 256
= 11+6
= 17
4
Data Structures and Applications, MUSE
2. = a*b+c
= *ab+c
= +*abc
3. = a+b-c
= +ab-c
= -+abc
4. = a*b-c/d
=*ab-c/d
=*ab-/cd
= -*ab/cd
5
Data Structures and Applications, MUSE
2. =a+b-c
=ab+-c
=ab+c-
3. =a+b*c
=a+bc*
=abc*+
4. = a*b-c/d
= ab*-c/d
= ab*-cd/
= ab*cd/-
5. = ((A+(B-C)*D)^E+F)
= ((A+BC-*D)^E+F)
= ((A+BC-D*)^E+F)
= (ABC-D*+^E+F)
= (ABC-D*+E^+F)
= ABC-D*+E^F+
6. = X^Y^Z-M+N+P/Q
= X^YZ^-M+N+P/Q
= XYZ^^-M+N+P/Q
= XYZ^^-M+N+PQ/
= XYZ^^M-+N+PQ/
= XYZ^^M-N++PQ/
= XYZ^^M-N+PQ/+
6
Data Structures and Applications, MUSE
4 C +/ ABC
5 ABC/+
Example 2: A-B/C*D+E
Example 3: K+L-M*N+(O^P)*W/U/V*T+Q
Steps Scanned Symbol Stack Output
0 K K
1 + + K
2 L + KL
3 - - KL+
4 M - KL+M
5 * -* KL+M
6 N -* KL+MN
7 + + KL+MN-*
8 ( +( KL+MN-*
9 O +( KL+MN-*O
10 ^ +(^ KL+MN-*O
11 P +(^ KL+MN-*OP
12 ) + KL+MN-*OP^
13 * +* KL+MN-*OP^
14 W +* KL+MN-*OP^W
15 / +/ KL+MN-*OP^W*
16 U +/ KL+MN-*OP^W*U
17 / +/ KL+MN-*OP^W*U/
18 V +/ KL+MN-*OP^W*U/V
19 * +* KL+MN-*OP^W*U/V/
20 T +* KL+MN-*OP^W*U/V/T
21 + + KL+MN-*OP^W*U/V/T*+
22 Q + KL+MN-*OP^W*U/V/T*+Q
23 + KL+MN-*OP^W*U/V/T*+Q+
Example 4: K+L-M*N+(O^P)*W/U/V*T+Q^J^A
7
Data Structures and Applications, MUSE
5 * -* KL+M
6 N -* KL+MN
7 + + KL+MN-*
8 ( +( KL+MN-*
9 O +( KL+MN-*O
10 ^ +(^ KL+MN-*O
11 P +(^ KL+MN-*OP
12 ) + KL+MN-*OP^
13 * +* KL+MN-*OP^
14 W +* KL+MN-*OP^W
15 / +/ KL+MN-*OP^W*
16 U +/ KL+MN-*OP^W*U
17 / +/ KL+MN-*OP^W*U/
18 V +/ KL+MN-*OP^W*U/V
19 * +* KL+MN-*OP^W*U/V/
20 T +* KL+MN-*OP^W*U/V/T
21 + + KL+MN-*OP^W*U/V/T*+
22 Q + KL+MN-*OP^W*U/V/T*+Q
23 ^ +^ KL+MN-*OP^W*U/V/T*+Q
24 J +^ KL+MN-*OP^W*U/V/T*+QJ
25 ^ +^^ KL+MN-*OP^W*U/V/T*+QJ
26 A +^^ KL+MN-*OP^W*U/V/T*+QJA
27 +^^ KL+MN-*OP^W*U/V/T*+QJA^^+
Example 2: 53+62/*35*+
= 53+62/*35*+
= 862/*35*+
= 83*35*+
= 2435*+
= 2415+
= 39
Example 3: Assume a=2, b=3, c=4, d=16, e=2, f=3. Evaluate following postfix expression
abc*+def^/-
= abc*+def^/-
= 234*+1623^/-
= 212+1623^/-
= 141623^/-
= 14168/-
= 142-
= 12
8
Data Structures and Applications, MUSE
Example 2: 632-5*+1^7+
Steps Scanned Symbol Stack Output
0 6 6
1 3 63
2 2 632
3 - 61 1
4 5 615
5 * 65 5
6 + 11 11
7 1 11 1
8 ^ 11 11
9 7 11 7
10 + 18 18
Example 3: Convert the given expression to postfix expression and then evaluate the postfix
expression using stack. (1+(2-3)*4)
First perform Conversion of postfix expression
9
Data Structures and Applications, MUSE
4 2 (+( 12
5 - (+(- 12
6 3 (+(- 123
7 ) (+ 123-
8 * (+* 12 3-
9 4 (+* 1 2 3 -4
10 ) 1 2 3 -4 * +
10
Data Structures and Applications, MUSE
Recursion
Recursion is a method of solving the problem where the solution to a problem depends on solutions to
smaller instances of the same problem.
• Direct Recursion
• Indirect Recursion
Direct recursion
Indirect recursion
A function which contains call to another function which in turn contains calls another function, and so
on.
• Base case
• General case
Base case
General case:
The statement that reduces the size of the problem is called general case.
This is done by calling the same function with reduced size.
In general, recursive function of factorial problem can be written as,
11
Data Structures and Applications, MUSE
Limitations of Recursion
• Recursive solutions may involve extensive overhead because they use function calls.
• Each time you make a call, you use up some of your memory allocation. If recursion is
deep, then you may run out of memory.
Example Programs,
Write a C program to find a factorial of number using recursion.
#include<stdio.h>
int fact(int);
void main( )
{
int n, res;
Output
enter the number to find its factorial
5
factorial of 5 = 120
12
Data Structures and Applications, MUSE
Fibonacci series
#include<stdio.h>
int Fibonacci(int);
void main()
{
int n, i = 0, c;
printf(" enter the number of terms\n");
scanf("%d", &n);
printf("Fibonacci series\n");
for ( c = 1 ; c <= n ; c++ )
{
printf("%d\n", Fibonacci(i));
i++;
}
}
int Fibonacci(int n)
{
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return ( Fibonacci(n-1) + Fibonacci(n-2) );
}
Output
enter the number of terms
5
01123
The greatest common divisor (GCD) of two integers a and b is the greatest integer that divides both a
and b with no remainder.
gcd(a,b) = gcd (b, a mod b) i.e., if only a > b again and again call a mod b then stop when,
gcd(a,0) = a
Algorithm:
• Divide a by b and assign the value reminder to c.
13
Data Structures and Applications, MUSE
a b a/b
30 18 16
18 12 6
12 6 0
6 0
gcd(30,18) = 6
Write a program to find GCD and LCM of two numbers using concept of functions.
#include<stdio.h>
int hcf(int, int);
int main( )
{
int x, y, gcd, lcm;
OUTPUT
14
Data Structures and Applications, MUSE
Tower of Hanoi
It is a mathematical puzzle, where we have three roads (Beginning, Auxiliary, End) and ‘N’ disks. The
objective of the puzzle is to move the ‘N’ disks to destination road, obeying the following rules.
• Only one disk can be moved at a time.
• A disk can only be moved, if it is the uppermost disk.
• No disk may be placed on the top of the smaller disk.
Example 1: n = 1
Output:
In other words,
n=l: A→C
15
Data Structures and Applications, MUSE
Example 1: n = 2
Output:
1. Move top disk from peg A to peg B.
2. Move top disk from peg A to peg C.
3. Move top disk from peg B to peg C.
In other words,
n=2: A→B, A→C, B→C,
Example 1: n = 3
16
Data Structures and Applications, MUSE
17
Data Structures and Applications, MUSE
Output:
1. Move top disk from peg A to peg C.
2. Move top disk from peg A to peg B.
3. Move top disk from peg C to peg B.
4. Move top disk from peg A to peg C.
5. Move top disk from peg B to peg A.
6. Move top disk from peg B to peg C.
7. Move top disk from peg A to peg C.
In other words,
n=3: A→C, A→B, C→B, A→C, B→A, B→C, A→C
The recursive procedure call for tower of Hanoi problem is, general notation is,
Example 1: n = 4
18
Data Structures and Applications, MUSE
Ackerman’s Function
It is a function with two arguments each of which can be assigned any non-negative integers i.e.,
0,1,2… is defined as follows.
Definition
• If m = 0 then A (m, n) = n+1
• If m = 0 but n = 0 then, A (m, n) = A (m-1, 1)
• If m = 0 but n = 0 then, A (m, n) = A (m-1, A (m, n-1))
A (1, 1) = A(m, n)
= A (m-1, A (m, n-1))
= A (1-1, A (1, 1-1))
= A (0, A (1, 0))
= A (0, A (m-1, 1))
= A (0, A (1-1, 1))
= A (0, A (0, 1))
= A (0, n+1)
= A (0, 1+1)
= A (0, 2)
= n+1
=2+1
=3
19
Data Structures and Applications, MUSE
Queues
Definition
A queue is linear data structure or abstract data type of elements in the insertion can take place at
only one end called “rear” and deletion can take place at only on end called “front”.
The insertion and deletion of elements in queue will follow “first in first out (FIFO)” or “last in last or
(LILO)”.
Types of Queues
Applications of queue
It is used when you want share serve the request on the single shared resource.
• Printers: shared with different computers.
• Customer care service: to put the people on hold until they representative attains the call.
• Processors: is placed in queue (ex: in operating systems and job scheduling process).
20
Data Structures and Applications, MUSE
enqueue(20);
enqueue(30);
display();
peek();
dequeue();
peek();
display();
}
void enqueue(int x)
{
if (rear == N-1)
printf(“overflow condition\n”);
elseif(front == -1 && rear == -1)
{
front = rear = 0;
queue[rear] = x;
}
else
{
rear++;
queue[rear]=x;
}
}
void dequeue()
{
if (front == -1 && rear == -1)
printf(“underflow condition\n”);
elseif(front == rear)
front = rear = -1;
else
{
printf(“%d”, queue[front]);
front++;
}
void display()
{
if (front == -1 && rear == -1)
printf(“queue is empty\n”);
else
{
for(i=front; i<rear+1; i++)
printf(“%d”, queue[i]);
}
}
void peek()
{
if(front == -1&&rear == -1)
printf(“queue is empty\n”);
else
printf(“%d”, queue[front]);
}
21
Data Structures and Applications, MUSE
10 20 30
10
10
20
20 30
22
Data Structures and Applications, MUSE
void enqueue(int x)
{
if (front == -1 && rear == -1)
{
front = rear = 0;
queue[rear] = x;
}
elseif((rear+1)%N)==front))
printf(“queue is full\n”);
else
{
rear = (rear+1)%N;
queue[rear] = x;
}
}
void dequeue()
{
if (front == -1 && rear == -1)
printf(“queue is empty\n”);
elseif(front == rear)
front = rear = -1;
else
{
printf(“%d”, queue[front]);
front=(front+1)%N;
}
}
void display()
{
if (front == -1 && rear == -1)
printf(“queue is empty\n”);
23
Data Structures and Applications, MUSE
else
{
for(i=front; i<rear+1; i++)
printf(“%d”, queue[i]);
}
}
void peek()
{
if(front == -1&&rear == -1)
printf(“queue is empty\n”);
else
printf(“%d”, queue[front]);
}
10 20 30 40 50
10
24
Data Structures and Applications, MUSE
20
void enqueue(int x)
{
if((rear+1)%N)==front))
{
printf(“queue is full and increase the by 1\n”);
N++;
q = (int*) realloc (q, N* sizeof(int));
for(i=N-2; i>front; i--)
{
q[i+1]=q[i];
}
front++;
else
{
25
Data Structures and Applications, MUSE
rear = (rear+1)%N;
queue[rear] = x;
}
}
void dequeue()
{
if (front == -1 && rear == -1)
printf(“queue is empty\n”);
else
{
printf(“deleted element is %d”, queue[front]);
N--;
q = (int*) realloc (q, N* sizeof(int));
for(i=front-1; i<N; i++)
q[i]=q[i+1];
front--;
}
}
A deque is linear list in which elements can be added or removed at either end. Insertion is possible at
both front and rear end. Similarly, deletion can be done at front and rear end.
Types of deque
• Input restricted
• Output restricted
Input restricted
output restricted
26
Data Structures and Applications, MUSE
Deque operations
deletefront();
deleterear(); dequeue
getfront(); == isfull()
getrear(); ==isempty()
Applications of deque
#define N 5
int deque[5];
int f = -1;
int r = -1;
void main()
{
enqueuefront(1);
enqueuefront(2);
enqueuerear(-1);
enqueuerear(0);
enqueuefront(5);
enqueuerear(4);
display();
getfront();
getrear();
dequeuefront();
dequeuerear();
dequeuefront();
}
void enqueuefront(int x)
{
if(f==0&&N-1|| front==rear+1)
printf(“deque is full\n”);
elseif(f==-1 &&r==-1)
{
f=r=0;
deque[f] = x;
}
elseif(f==0)
27
Data Structures and Applications, MUSE
{
f=N-1;
deque[f]=x;
}
else
{
f--;
deque[f]=x;
}
}
void enqueuerear(int x)
{
if(f==0&&N-1|| front==rear+1)
printf(“deque is full\n”);
elseif(f==-1 &&r==-1)
{
f=r=0;
deque[f] = x;
}
elseif(r==N-1)
{
r=0;
deque[f]=x;
}
else
{
r++;
deque[r]=x;
}
}
void display()
{
int i=f;
while(i!=rear)
{
printf(“%d”, deque [i])
i=(i+1)%N;
}
printf(“%d”, deque[rear]);
}
void getfront()
{
printf(“%d”, deque[front]);
}
void getrear()
{
printf(“%d”, deque[rear]);
}
void dequeuefront()
{
28
Data Structures and Applications, MUSE
if(f==-1&& r==-1)
printf(“deque is full\n”);
elseif(f==r)
f=r=-1;
elseif(f==N-1)
{
printf(“%d”, deque[f]);
f=0;
}
else
{
printf(“%d”, deque[f]);
f++;
}
}
void dequeuerear()
{
if(f==-1&& r==-1)
printf(“deque is full\n”);
elseif(f==r)
f=r=-1;
elseif(r==0)
{
printf(“%d”, deque[r]);
r=N-1;
}
else
{
printf(“%d”, deque[r]);
r--;
}
}
Output enqueuefront
29
Data Structures and Applications, MUSE
Output enqueuerear
Output enqueuefront
queue is full
Output display
5 2 1 -1 0
Output getfront
Output getfront
Output dequeuefront
Output dequeuerear
30
Data Structures and Applications, MUSE
Output dequeuefront
Priority Queue
It is special type of queue in which each element is associated with a “priority value”. Elements are
served on the basis of their priority. i.e., higher priority elements are served first.
If the elements with the same priority occur, they are served according to their order (FIFO).
• Arrays
• Linked list
• Heap
void insert()
{
int i;
if (r== N-1)
printf(“queue is full\n”);
i=r;
while(i>=0&& x<q[i])
{
q[i+1] = q[i];
i--;
}
q[i+1]=x;
r=r+1;
}
31
Data Structures and Applications, MUSE
void insert()
{
int i;
if (r== N-1)
printf(“queue is full\n”);
i=r;
while(i>=0&& x>q[i])
{
q[i+1] = q[i];
i--;
}
q[i+1]=x;
r=r+1;
}
32
Data Structures and Applications, MUSE
A Mazing Problem
A maze is confusing network of paths through which it is very difficult to find one’s way. A maze is
represented as 2D array in which,
• We assume that rat starts at the top left and is to exit at bottom right.
• The maze can be represented as 2D array, the location of the rat in the maze can be
determined by row and column position.
• Let (i,j) is the current position of the rat in maze where ‘I’ is the row index and j is the column
index.
• Rat can move in the 8 possible directions N, NE, E, SE, S, SW, W and NW respectively.
• The rat can move in all 8 directions but this not true all time. If the position of rat is on any
border, then it cannot move in all directions. So to avoid checking the border conditions, we
can surround the maze by adding one’s to above figure indicate the barriers for the entrance
of rat.
33
Data Structures and Applications, MUSE
Either we add -1, 1 or 0 to (i , j) to get the new position. These values that we add to find the new
position is called offset values.
Multiple stacks
In many applications and algorithm several stacks are needed. For these we can create more than one
stack in same array. This technique is called multiple stack.
• For ‘n’ number of stacks, one has to divide the available array into ‘n’ equal segments having
equal memory.
• If size of stack is known, then the division of available memory is done according to the size
of the stack.
34
Data Structures and Applications, MUSE
To find the initial value of top of each of stack i.e., top[0], top[1], top[2], top[3] use the expression,
top[i] = m/n * i-1
where, i=0 to n.
To find the boundary of each of the stack, cop initial value of top[0] to boundary[0] and so on,
35
Data Structures and Applications, MUSE
36