Dsa Notes Unit IV,V,Vi (1)
Dsa Notes Unit IV,V,Vi (1)
Introduction to Stack :
Stack is a linear data structure which follows a particular order in which the
operations are performed. It is a simple data structure that allows adding and removing
elements in a particular order.
Every time an element is added, it goes on the top of the stack and the only element
that can be removed is the element that is at the top of the stack.
Stack is an ordered list of similar data type. Stack is a LIFO (Last in First out)
structure or we can say FILO (First in Last out).
push() function is used to insert new elements into the Stack and pop() function is
used to remove an element from the stack.
Both insertion and removal are allowed at only one end of Stack called Top. Stack is
said to be in Overflow state when it is completely full and is said to be in Underflow state
if it is completely empty.
Array representation of Stack :
Stack data structure can be represented in memory in various forms. Linear array is the
most representation of stack in memory as :
In the above representation, following are the two special pointers used, as :
i. TOP : This pointer indicates location of the last element added in stack and is useful
for any push and pop operation.
ii. MAXSTACK : It is a value that indicates size or maximum number of elements in
stack.
When MAXSTACK = NULL, it means that the stack is not allocated.
If TOP = NULL, it means that the stack is empty.
If TOP = MAXSTACK, it means that the list is full.
PUSH Operation : Inserting a new element in stack is called PUSH operation. As long
as TOP != MAXSTACK, PUSH operation can be performed.
Algorithm : STACK_PUSH(STACK, TOP, MAXSTACK, ITEM)
Let STACK be the stack in memory with TOP & MAXSTACK pointers. ITEM is the element
to be inserted.
This algorithm confirms if the stack has space & then inserts new element.
Step 1 : If TOP = MAXSTACK then
Write OVERFLOW & EXIT
else
Set TOP := TOP +1
Set STACK[TOP] := ITEM
Step 2 : EXIT
POP Operation : Removing an existing element from stack is called POP operation.
Algorithm : STACK_POP(STACK, TOP, MAXSTACK, ITEM)
Let STACK be the stack in memory with TOP & MAXSTACK pointers. ITEM is the element
to be deleted.
This algorithm confirms that TOP != NULL & if it is the stack is underflow & hence no
deletion is possible.
Step 1 : If TOP = NULL then
Write UNDERFLOW & EXIT
else
Set ITEM := STACK[TOP]
Set TOP := TOP - 1
Step 2 : EXIT
As like Linked LIST, STACK also allocates memory in two forms, as :
1. Static Memory Allocation : Static Memory Allocation does not use the concept of
HEAP, thus it works similar to array where no insertion & deletion is possible during
run-time.
2. Dynamic Memory Allocation : Dynamic Memory Allocation in STACK is done using
the concept of HEAP.
Arithmetic Expressions :
In any algorithm or program, each step, sentence or instruction is used for specific
purpose. An instruction or step which performs an arithmetic operation is known as an
Arithmetic Expression.
For e.g. Set A := B + C
An expression may have single or multiple operators, hence an expression can also
be defined as – “An Instruction with collection of operators & operands in a specific
order.”
When a single expression uses multiple operators, it is necessary to decide which
operator executes first? The rule by which execution of operator is decided is called
operator precedence.
According to mathematical rules, different operators have following precedence level, as
Highest - [^]
Higher - [ * / / ]
Lower – [ + / - / = ]
If there are different operators in an expression, the operator with highest
precedence is executed first.
A = 10 + 5 * 3
Here,
A = 10 + 15
A = 25
If the expression contains multiple operators of same level, then execution follows
“Left – to – Right” order, as :
A = 10 + 5 – 3
Here,
A = 15 – 3
A = 12
The default precedence can be changed using parenthesis, as :
A = (10 + 5) * 3
Here,
A = 15 * 3
A = 45
The most common arithmetic operations are represented using operator symbols such as
A + B, A – B, A * B, A/B
Polish Notations :
Expressions with same level operators or single operators does not clearly specify the
execution sequence, i.e. If A + B is the expression then it may be A+B or B+A.
But for processor it must be clear that what is the sequence & position of operand. For
this purpose Polish Notations are recommended.
The operator representation rules designed by mathematician from POLAND are
popularly known as Polish Notations.
According to polish notations, operators should be placed before operands to show
the sequence & position as :
+AB, -CD, *EF, /BA
Polish notations uses three different types of notations, as :
Infix Notation
Prefix Notation
Postfix Notation
1. Infix Notation :
In Infix Notation the binary operator is between the two operands. It is a regular
arithmetic expression given by parenthesis.
It converts the regular arithmetic expression into polish notation using square
brackets[ ].
For e.g.
(A+B)*C = [A+B]*C
2. Pre-fix Notation :
In Pre-fix Notation the binary operator preceeds the two operands. It is a regular
arithmetic expression where operators are placed before operands.
For e.g. +AB, -AB, *AB, /AB
3. Post-fix Notation :
In some cases, polish notations are represented in reverse order, hence called
reverse polish notations.
In this operators are placed after operands, thus also called Post-fix notations.
For e.g. AB+, AB-, AB*, AB/
Evaluation of Post-fix Expression :
The Postfix notation is used to represent algebraic expressions. The expressions
written in postfix form are evaluated faster compared to infix notation as parenthesis are
not required in Postfix expressions.
Following is algorithm for evaluation postfix expressions :
Step 1 : Create a stack to store operands (or values).
Step 2 : Scan the given expression and do following for every scanned element.
a) If the element is a number, push it into the stack.
b) If the element is a operator, pop operands for the operator from stack. Evaluate
the operator and push the result back to the stack
Step 3 : When the expression is ended, the number in the stack is the final answer.
Let the given expression be “2 3 1 * + 9 -“. We scan all elements one by one, as
2) Scan ‘3’, again a number, push it to stack, stack now contains ‘2 3’ (from bottom to top)
4) Scan ‘*’, it’s an operator, pop two operands from stack, apply the * operator on
operands, we get 3*1 which results in 3. We push the result ‘3’ to stack. Stack now
becomes ‘2 3’.
5) Scan ‘+’, it’s an operator, pop two operands from stack, apply the + operator on
operands, we get 3 + 2 which results in 5. We push the result ‘5’ to stack. Stack now
becomes ‘5’.
6) Scan ‘9’, it’s a number, we push it to the stack. Stack now becomes ‘5 9’.
7) Scan ‘-‘, it’s an operator, pop two operands from stack, apply the – operator on
operands, we get 5 – 9 which results in -4. We push the result ‘-4’ to stack. Stack now
becomes ‘-4’.
8) There are no more elements to scan, we return the top element from stack (which is
the only element left in stack).
Post-fix Expression Operators Stack
231*+9- 2
31*+9- 23
1*+9- 231
*+9- 3*1=3 23
+9- 2+3=5 5
9- 59
- 5 – 9 = -4 -4
Recursion :
In programming, algorithm & programs are divided into smaller executable
modules. Each such smaller executable module is called a method or a procedure.
It is very common that one procedure calls another procedure. Thus, there will be
one caller procedure & called procedure.
From caller procedure execution control is transferred to called procedure.
But in some real life applications, a procedure also calls itself, i.e. the caller & the
called procedure both are same.
The technique of a procedure or a function calling itself is called recursion.
The procedure which is calling itself is known as recursive procedure. To avoid the
chances of infinite calls, a recursive function is defined such that it must have following
two properties :
1. It must be using a base criteria (Condition)
2. In each calling, the counter should get closer to the base criteria.
Use of such recursive procedure is very common while calculating factorial of a number
as :
n! = 1*2*3*…..*n
The factorial of a negative number doesn't exist. And the factorial of 0 is 1.
Step 1 : Start
Step 2 : Read number n
Step 3 : Call factorial(n)
Step 4 : Print factorial f
Step 5 : Stop
factorial(n)
Step 1 : if n<1 then
return 1
Step 2 : else
f=n*factorial(n-1)
Step 3 : Return f
Program to get input of a number & calculate its factorial using recursion.
#include<iostream.h>
void main( )
{
int N, f;
clrscr();
cout<<“Enter a no. : “;
cin>>N;
f=FACT(N);
cout<<“Factorial : “<<f;
}
int FACT(int n)
{
if(n>=1)
return n * FACT(n-1);
else
return 1;
}
5! = 5*4*3*2*1 = 120
5 * FACT(4) 24 * 5
4 * FACT(3) 6*4
3 * FACT(2) 2*3
2 * FACT(1) 1*2
1 * FACT(0) return 1
Fibonacci :
The Fibonacci Sequence is the series of numbers: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
In this, the next number is found by adding up the two numbers before it:
2 is calculated by adding the two numbers preceding it (1+1),
3 is calculated by adding the two numbers preceding it (1+2),
5 is (2+3), and so on..
In the above example, 0 and 1 are the first two terms of the series. These two terms
are printed directly. The third term is made by adding the first two terms.
Step 1 : Start
Step 2 : Read number n
Step 3 : Call fibo(n)
Step 4 : Print n
Step 5 : Stop
fibo(n)
Step 1 : if n<2 then
return n
Step 2 : else
return fibo(n-1) + fibo(n-2)
Step 3 : Exit
Program to get input of a number & display its Fibonacci number.
#include<iostream.h>
void main( )
{
int N, f;
clrscr();
cout<<“Enter a no. : “;
cin>>N;
f=fibo(N);
cout<<“Fibonacci Series : “<<f;
}
int Fibo(int n)
{
if(n<2)
return n;
else
return (fibo(n-1) + fibo(n-2));
}
Unit V : Queue
Introduction to Queues
Linked representation of Queue
Insertion & Deletion on Queue
Dequeue
Priority Queue
Introduction to Queues :
Queue is a linear data structure where the first element is inserted from one end
called REAR and deleted from the other end called FRONT.
Queue is also called as FIFO [ First In First Out] data structure. According to its FIFO
structure, element inserted first will also be removed first.
Front pointer is used to get the first data item from a queue.
Rear pointer is used to get the last item from a queue.
Like Stacks, Queues can also be represented in memory in two ways, as :
Using the contiguous memory like an array
Using the non-contiguous memory like a linked list
Deletion in Queue :
Queue allows deletion operation that refers to deleting an existing element from
the queue. Deletion in queue is always done using FRONT pointer and generally after
successful deletion, FRONT pointer is to be updated.
While performing deletion, following possibilities are considered, as :
1. Queue is empty : When FRONT & REAR are NULL, it means queue contains no
elements, i.e. underflow condition.
2. Queue with one element : When FRONT & REAR pointers points to the first
element, after deletion of that element, both values become NULL.
3. Queue with few elements : When there are few elements in the queue, after
deletion of first element, FRONT pointer is incremented by 1.
Priority Queue :
Generally queue stores & processes data elements using FIFO rule. But in many
cases, FIFO cannot be applied. In such cases, modified form of queue is used called Priority
Queue.
A special implementation of queue which processes data elements on the basis of
a priority value is called “Priority Queue”. Priority is a relative importance of a data
element as compared to others.
In priority queue, data element with highest priority will be executed first. If
elements with the same priority occur, they are served according to their order in the
queue.
In a queue, the first-in-first-out rule is implemented whereas, in a priority queue, the
values are removed on the basis of priority. The element with the highest priority is
removed first.
The common implementation of priority queue is found in time sharing multitasking
operating system. Each element is assigned a positive number as priority number[PRN].
The processing principle of priority queue is based on following rules :
1. If elements of different priorities are available then element with highest priority
will be processed first.
2. If elements of same priorities are present then processing is done according to FIFO.
Memory Representation : A priority queue can be represented in memory as linked list
with three parallel arrays, as : INFO, LINK & PRN. INFO contains the data element, LINK
contains address of next node & PRN contains priority number.
Unit VI : Tree & Graph
Binary Trees, Representation of Binary trees in memory.
Traversing Binary Tree (Pre-order, In-order, Post-order)
Header Nodes, Threads
Graph Theory Terminology
Sequential representation of Graph
Operations on Graph
The topmost node in the tree is called the root. An empty tree is represented
by NULL pointer.
A representation of binary tree can be shown as :
A binary tree T with root node & other nodes forms two sub-trees T1 & T2, as :
The given binary tree shows following characteristics :
1. Tree contains total 7 nodes represented using alphabets from A to G.
2. The topmost node A represents root node.
3. B is the left successor & C is the right successor of root node A.
4. The left sub-tree consists of B D E & the right sub-tree consists of C F G.
Traversing Binary Tree :
Traversing is one of the most fundamental operations performed on any data
structure. Traversing refers to processing or visiting each node in tree atleast once.
A binary tree is a non-linear data structure in which nodes are hierarchically organized
on which traversing can be performed in three ways :
Pre-order Traversal
In-order Traversal
Post-order Traversal
Header Node :
A binary tree in a computer program can be represented in memory using linked list.
The specialized form of linked list in which each node has one data part & two address
parts, known as double linked list.
When a double linked list is used to represent a binary tree, the root node of double
linked list shows following properties :
The left address part of root node points to left sub-tree.
The right address part of root node points to right sub-tree.
When a binary tree is represented using double linked list, a special node is assigned
to point root node of binary tree, called as Header node.
There is one more node used to point header node which is called Head Node. If T
is a given binary tree, its double linked list representation can be given as :
The double linked list representation provides following conclusions on binary tree :
1. If ROOT[left] = NULL, it means binary tree does not have left sub-tree.
2. If ROOT[right] = NULL, it means binary tree does not have right sub-tree.
3. If ROOT[left] = NULL & ROOT[right] = NULL, it means binary tree contains only root
node.
4. If Header = NULL, it means binary tree is empty.
Threads :
In a double linked list representation of binary tree, there are so many address parts that
are wasted & very few parts are used, as :
Total address parts : 12
Total used parts : 5
Total unused parts : 7
To avoid such memory wastage, a computer program supports use of threads. The
pointer which points to the higher level node or the parent node is called thread.
The binary tree with such thread is called threaded tree.
In threaded tree, forward link i.e. from higher level to lower level (Parent to child) is shown
by a solid line ( ) and reverse link i.e. from lower level to higher level (Child node to
parent node) is shown by a dotted line (------).
Such threaded tree is very useful while performing In-order traversing (left-root-right).
1. One way In-order threading : In this type of threaded tree, each higher level node
receives atleast one reverse link from its sub-node.
Total address parts : 12
Total used parts : 8
Total unused parts : 4
2. Two way In-order threading : In this type of threaded tree, each higher level node
receives multiple reverse links from its sub-node.
Total address parts : 12
Total used parts : 9
Total unused parts : 3
Graph :
A Graph is a non-linear data structure consisting of finite nodes and edges. The
nodes are sometimes also referred to as vertices and the edges are lines or arcs that
connect any two nodes in the graph.
A graph G can be defined as an ordered set G(V, E) where V(G) represents the
set of vertices and E(G) represents the set of edges which are used to connect these
vertices.
In the given graph,
V = {a, b, c, d, e}
E = {ab, ac, bd, cd, de}
Graph Terminology :
We use the following terms in graph data structure :
1. Vertex : A single individual data element of a graph is called as a Vertex. Vertex is
also known as a node. In the given graph, a,b,c,d,e are known as vertices.
2. Edge : An edge is a connecting link between two vertices. Edge is also known
as Arc. In the given graph, (a,b), (a,c), (c,d), (b,d), (d,e) are the edges.
Edges are of three types :
a) Undirected Edge - An undirected edge is a bidirectional edge. If there is undirected
edge between vertices A and B then edge (A , B) is equal to edge (B , A).
b) Directed Edge - A directed edge is a unidirectional edge. If there is directed edge
between vertices A and B then edge (A , B) is not equal to edge (B , A).
c) Weighted Edge - A weighted edge is a edge with value (cost) on it.
A directed graph is a set of vertices (nodes) connected by edges, with each node having
a direction associated with it. Edges are usually represented by arrows pointing in the
direction the graph can be traversed. A directed graph and its adjacency matrix
representation is shown in the following figure:
Operations on Graph :
1. Add/Remove Vertex : This is the simplest operation in the graph. You simply add a
vertex to a graph. It need not be connected to any other vertex through an edge.
When removing a vertex, you must remove all edges originating from and ending
at the deleted vertex.
2. Add/Remove Edge : This operation adds or removes an edge between two vertices.
When all the edges originating from and ending at a vertex are deleted, the vertex
becomes an isolated vertex.
3. Breadth-First Search (BFS) : BFS horizontally traverses the graph i.e. it traverses all
the nodes at a single level before proceeding to the next level.
The BFS algorithm starts at the top of the first node in the graph and then
traverses all the adjacent nodes to it. Once all the adjacent nodes are traversed, the
algorithm repeats the same procedure for child nodes.
Traversing the above graph in BFS fashion would result from
A -> B -> C -> D -> E -> F -> G.
4. Depth First Search (DFS) : Depth First Search or DFS traverses the graph vertically.
It starts with the root node or the first node of the graph and traverses all the child
nodes before moving to the adjacent nodes.
Traversing the above graph in DFS fashion would result from
A -> B -> E -> F -> C -> G -> D.
Assignment IV / Internal II Questions :
1. Explain Push & Pop operations on stack.
2. Describe priority queue.
3. Explain representation of binary trees in memory.
4. Explain operations on graph.
5. Explain the concept of Polish notations.
6. Describe traversing of binary tree.
7. Explain calculating factorial of a number using recursion.
8. Explain deletion algorithm on queue.