DSA UNIT-5 Notes 2023
DSA UNIT-5 Notes 2023
Graph is a non linear data structure. It contains set of points known as nodes (or vertices) and
set of links known as edges (or Arcs). Here edges are used to connect the vertices. A graph is
defined as follows...
§
Graph is a collection of vertices and arcs in which vertices are connected with arcs
Graph is a collection of nodes and edges in which nodes are connected with edges
Generally, a graph G is represented as G = ( V , E ), where V is set of vertices and E is set of
edges.
Example
Vertex
Individual data element of a graph is called as Vertex. Vertex is also known as node. In
above example graph, A, B, C, D & E are known as vertices.
Edge
An edge is a connecting link between two vertices. Edge is also known as Arc. An edge
is represented as (startingVertex, endingVertex). For example, in above graph the link
between vertices A and B is represented as (A,B). In above example graph, there are 7
edges (i.e., (A,B), (A,C), (A,D), (B,D), (B,E), (C,D), (D,E)).
Undirected Graph
A graph with only undirected edges is said to be undirected graph.
Directed Graph
A graph with only directed edges is said to be directed graph.
Mixed Graph
A graph with both undirected and directed edges is said to be mixed graph.
Origin
If a edge is directed, its first endpoint is said to be the origin of it.
Destination
If a edge is directed, its first endpoint is said to be the origin of it and the other
endpoint is said to be the destination of that edge.
Adjacent
If there is a edge between vertices A and B then both A and B are said to be adjacent.
In other words, vertices A and B are said to be adjacent if there is a edge between them.
Incident
Edge is said to be incident on a vertex if the vertex is one of the endpoints of that edge.
Outgoing Edge
A directed edge is said to be outgoing edge on its origin vertex.
Incoming Edge
A directed edge is said to be incoming edge on its destination vertex.
Degree
Total number of edges connected to a vertex is said to be degree of that vertex.
Indegree
Total number of incoming edges connected to a vertex is said to be indegree of
that vertex.
Outdegree
Total number of outgoing edges connected to a vertex is said to be outdegree of
that vertex.
Self-loop
Edge (undirected or directed) is a self-loop if its two endpoints coincide with each other.
Simple Graph
A graph is said to be simple if there are no parallel and self-loop edges.
Path
A path is a sequence of alternate vertices and edges that starts at a vertex and ends
at other vertex such that each edge is incident to its predecessor and successor vertex.
Graph Representations
Graph data structure is represented using following representations...
1. Adjacency Matrix
2. Incidence Matrix
3. Adjacency List
Adjacency Matrix
In this representation, graph is represented using a matrix of size total number of
vertices by total number of vertices. That means graph with 4 vertices is represented
using a matrix of size 4X4. In this matrix, both rows and columns represents vertices.
This matrix is filled with either 1 or 0. Here, 1 represents that there is a edge from row
vertex to column vertex and 0 represents that there is no edge from row vertex to
column vertex.
Adjacency List
In this representation, every vertex of a graph contains list of its adjacent vertices.
For example, consider the following directed graph representation implemented using
linked list...
Graph traversal is a technique used for searching vertex in a graph. The graph traversal is also
used to decide the order of vertices to be visited in the search process. A graph traversal finds
the edges to be used in the search process without creating loops. That means using graph
traversal we visit all the vertices of graph without getting into looping path.
There are two graph traversal techniques and they are as follows...
BFS traversal of a graph produces a spanning tree as final result. Spanning Tree is a graph
without loops. We use Queue data structure with maximum size of total number of vertices in
the graph to implement BFS traversal.
Queue
Status :
Output: A
Queue Status : B
S Output: A B S
Queue Status : C
G Output: A B S
Queue Status : G D E F
Output: A B S C
Queue Status : D E F H
Output: A B S C G
Queue Status : E F H
Output: A B S C G D
Queue Status : F H
Output: A B S C G D E
Queue Status : H
Output: A B S C G D E F
Queue Status :
Output: A B S C G D E F H
http://www.mathcs.emory.edu/~cheung/Courses/171/Syllabus/11-Graph/bfs.html
Solution:
Minimum Path P can be found by applying breadth first search algorithm that will begin at node A and will
end at E. the algorithm uses two queues,
namely QUEUE1 and QUEUE2. QUEUE1 holds all the nodes that are to be processed while QUEUE2 holds
all the nodes that are processed and deleted from QUEUE1.
1. QUEUE1 = {A}
2. QUEUE2 = {NULL}
2. Delete the Node A from QUEUE1 and insert all its neighbours. Insert Node A into QUEUE2
1. QUEUE1 = {B, D}
2. QUEUE2 = {A}
3. Delete the node B from QUEUE1 and insert all its neighbours. Insert node B into QUEUE2.
1. QUEUE1 = {D, C, F}
2. QUEUE2 = {A, B}
4. Delete the node D from QUEUE1 and insert all its neighbours. Since F is the only neighbour of it which has
been inserted, we will not insert it again. Insert node D into QUEUE2.
1. QUEUE1 = {C, F}
2. QUEUE2 = { A, B, D}
5. Delete the node C from QUEUE1 and insert all its neighbours. Add node C to QUEUE2.
1. QUEUE1 = {F, E, G}
2. QUEUE2 = {A, B, D, C}
6. Remove F from QUEUE1 and add all its neighbours. Since all of its neighbours has already been added,
we will not add them again. Add node F to QUEUE2.
1. QUEUE1 = {E, G}
2. QUEUE2 = {A, B, D, C, F}
7. Remove E from QUEUE1, all of E's neighbours has already been added to QUEUE1 therefore we will not
add them again. All the nodes are visited and the target node i.e. E is encountered into QUEUE2.
1. QUEUE1 = {G}
2. QUEUE2 = {A, B, D, C, F, E}
DFS traversal of a graph produces a spanning tree as final result. Spanning Tree is a graph
without loops. We use Stack data structure with maximum size of total number of vertices in
Step 2 - Select any vertex as starting point for traversal. Visit that vertex and push it on
to the Stack.
Step 3 - Visit any one of the non-visited adjacent vertices of a vertex which is at the top
Step 4 - Repeat step 3 until there is no new vertex to be visited from the vertex which
Step 5 - When there is no new vertex to visit then use back tracking and pop one
Step 7 - When stack becomes Empty, then produce final spanning tree by
Back tracking is coming back to the vertex from which we reached the current vertex.
Example
Example
Stack
status:
Output:
Stack status: A
B Output: A B
Stack status: A S
C Output: A B S
Stack status: A S C D
Output: A B S C
Stack status: A S
C Output: A B S C
Stack status: A S C E
Output: A B S D E
Stack status: A S C E H
Output: A B S D E H
Stack status: A S C E H G
Output: A B S D E H G
Stack status: A S C E H G F
Output: A B S C D E H G F
Stack status: A S C E H G
Output: A B S C D E H G F
Stack status:
Output: A B S C D E H G F
Example 3
Consider the graph G along with its adjacency list, given in the figure below. Calculate the
order to print all the nodes of the graph starting from node H, by using depth first search (DFS)
algorithm.
Solution :
Push H onto the stack
1. STACK : H
POP the top element of the stack i.e. H, print it and push all the neighbours of H onto the stack that are is
ready state.
1. Print H
2. STACK : A
Pop the top element of the stack i.e. A, print it and push all the neighbours of A onto the stack that are in
ready state.
1. Print A
2. Stack : B, D
Pop the top element of the stack i.e. D, print it and push all the neighbours of D onto the stack that are in
ready state.
1. Print D
2. Stack : B, F
Pop the top element of the stack i.e. F, print it and push all the neighbours of F onto the stack that
are in ready state.
1. Print F
2. Stack : B
Pop the top of the stack i.e. B and push all the neighbours
1. Print B
2. Stack : C
Pop the top of the stack i.e. C and push all the neighbors.
1. Print C
2. Stack : E, G
Pop the top of the stack i.e. G and push all its neighbors.
1. Print G
2. Stack : E
Pop the top of the stack i.e. E and push all its neighbors.
1. Print E
2. Stack :
Hence, the stack now becomes empty and all the nodes of the graph have been traversed.
H→ A→ D→ F→ B→ C→ G→ E
Spanning Tree
Spanning tree can be defined as a sub-graph of connected, undirected graph G that is a tree
produced by removing the desired number of edges from a graph. In other words, Spanning
tree is a non-cyclic sub-graph of a connected and undirected graph G that connects all the
vertices together. A graph G can have multiple spanning trees.
Minimum Spanning Tree
There can be weights assigned to every edge in a weighted graph. However, A minimum
spanning tree is a spanning tree which has minimal total weight. In other words, minimum
spanning tree is the one which contains the least weight among all other spanning tree of some
particular graph.
Given an undirected and connected graph G=(V,E), a spanning tree of the graph G is a
tree that spans G (that is, it includes every vertex of G) and is a subgraph of G (every
edge in the tree belongs to G)
The cost of the spanning tree is the sum of the weights of all the edges in the tree. There can
be many spanning trees. Minimum spanning tree is the spanning tree where the cost is
minimum among all the spanning trees. There also can be many minimum spanning trees.
Minimum spanning tree has direct application in the design of networks. It is used in
algorithms approximating the travelling salesman problem, multi-terminal minimum cut
problem and minimum-cost weighted perfect matching. Other practical applications are:
1. Cluster Analysis
2. Handwriting recognition
3. Image segmentation
Shortest path algorithms
In this section, we will discuss the algorithms to calculate the shortest path between
two nodes in a graph.
There are two algorithms which are being used for this purpose. Prim's
Algorithm
Kruskal's Algorithm
Prim's Algorithm
Step 3: Select an edge e connecting the tree vertex and fringe vertex that has minimum
weight , If including that edge creates a cycle, then reject that edge and look for the next least
weight edge.
Step 4: Add the selected edge and the vertex to the minimum spanning tree T [END OF LOOP]
Complexity-
Explanation-
If adjacency list is used to represent the graph, then using breadth first search, all the vertices
can be traversed in O(V + E) time.
We traverse all the vertices of graph using breadth first search and use a min heap for storing
the vertices not yet included in the MST.
To get the minimum weight edge, we use min heap as a priority queue.
Min heap operations like extracting minimum element and decreasing key value takes O(logV)
time.
= O((E + V)logV)
= O(ElogV)
This time complexity can be improved and reduced to O(E + VlogV) using Fibonacci heap.
Problem-01:
Construct the minimum spanning tree (MST) for the given graph using Prim’s Algorithm-
Solution-
Since all the vertices have been included in the MST, so we stop. Weight of
the MST
= 10 + 25 + 22 + 12 + 16 + 14
= 99 units
Problem-02:
Construct the minimum spanning tree (MST) for the given graph using Prim’s Algorithm-
The Minimum Spanning Tree (MST) obtained by the application of Prim’s Algorithm on given
graph is-
= 1 + 4 + 2 + 6 + 3 + 10
= 26 units
Example3
MST=14
Kruskal's Algorithm
Kruskal's Algorithm is used to find the minimum spanning tree for a connected weighted graph.
The main target of the algorithm is to find the subset of edges by using which, we can traverse
every vertex of the graph. Kruskal's algorithm follows greedy approach which finds an optimum
solution at every stage instead of focusing on a global optimum.
Step-01:
Sort all the edges from low weight to high weight.
Step-02:
Take the edge with the lowest weight and use it to connect the vertices of graph.
If adding an edge creates a cycle, then reject that edge and go for the next least weight edge.
Step-03:
Keep adding edges until all the vertices are connected and a Minimum Spanning Tree (MST) is
obtained.
Time Complexity-
• The next edge can be obtained in O(logE) time if graph has E edges.
• The value of E can be at most O(V2). So, O(logV) and O(logE) are same.
Special Case-
• If the edges are already sorted, then there is no need to construct min heap.
Construct the minimum spanning tree (MST) for the given graph using Kruskal’s Algorithm-
Since all the vertices have been included in the MST, so we stop. Weight of
the MST
= 10 + 25 + 22 + 12 + 16 + 14
= 99 units
Apply the Kruskal's algorithm on the graph given as follows.
The next step is to add AE, but we can't add that as it will cause a cycle. The next edge
The next edge to be added is AD, but it can't be added as it will contain a cycle. Hence, the
Solution-
• Kruskal’s Algorithm is preferred when the graph is sparse i.e. when there are
less number of edges in the graph like E = O(V) or when the edges are already
sorted or can be sorted in linear time.
• Prim’s Algorithm is preferred when the graph is dense i.e. when there are
large number of edges in the graph like E = O(V2) because we do not have to
pay much attention to the cycles by adding an edge as we primarily deal with
the vertices in Prim’s Algorithm.
Q2:Will both Prim’s Algorithm and Kruskal’s Algorithm always produce the same
Minimum Spanning Tree (MST) for any given graph?
Solution-
If all the edge weights are distinct, then both the algorithms are guaranteed to find the same
i.e. unique MST.
Example-
This example clearly illustrates when all the edge weights are distinct, both the algorithms
always produces the same MST having the same cost as shown.
If all the edge weights are not distinct, then both the algorithms may not always produce the
same i.e. unique MST but the cost of the MST produced would always be same in both the
cases.
Example-
This example clearly illustrates when in the given graph, all the edge weights are not
distinct, different MSTs could be produced by both the algorithms as shown but the
cost of the resulting MSTs from both the algorithms would always be same.
What is Search?
Step 2: Compare, the search element with the first element in the list.
Step 3: If both are matching, then display "Given element found!!!" and terminate
the function
Step 4: If both are not matching, then compare search element with the next
Step 5: Repeat steps 3 and 4 until the search element is compared with the last
Step 6: If the last element in the list is also doesn't match, then display "Element not
void main(){
int list[20],size,i,sElement;
What is Search?
Search is a process of finding a value in a list of values. In other words, searching is the
process of locating given value position in a list of values.
Step 3: Compare, the search element with the middle element in the sorted list.
Step 4: If both are matching, then display "Given element found!!!" and terminate
the function
Step 5: If both are not matching, then check whether the search element is smaller
Step 6: If the search element is smaller than middle element, then repeat steps 2, 3,
Step 7: If the search element is larger than middle element, then repeat steps 2, 3, 4
Step 8: Repeat the same process until we find the search element in the list or until
Step 9: If that element also doesn't match with the search element, then display
void main()
{
int first, last, middle, size, i, sElement, list[100];
clrscr();
first = 0;
last = size - 1;
middle = (first+last)/2;
Insertion Sort
Insertion sort algorithm arranges a list of elements in a particular order. In insertion sort
algorithm, every iteration moves an element from unsorted portion to sorted portion until
all the elements are sorted in the list.
Step 1: Asume that first element in the list is in sorted portion of the list and
Step 2: Consider first element from the unsorted list and insert that element into the
Step 3: Repeat the above process until all the elements from the unsorted list are
Sorting Logic
Following is the sample code for insrtion sort...
Example
void main(){
getch();
}
Selection Sort
Step 1: Select the first element of the list (i.e., Element at first position in the list).
Step 2: Compare the selected element with all other elements in the list.
Step 3: For every comparision, if any element is smaller than selected element (for
Step 4: Repeat the same procedure with next position in the list till the entire list is
sorted.
Sorting Logic
Following is the sample code for selection sort...
Example
int size,i,j,temp,list[100];
clrscr();
getch();
}
Quick Sort
Quick Sort
quicksort(list,0,size-1);
Suthoju Girija Rani – [email protected]
NGIT DSA 2023 UNIT-V Lecture Notes
getch();
}
}
}
Merge Sort
Suthoju Girija Rani – [email protected]
NGIT DSA 2023 UNIT-V Lecture Notes
ALGORITHM:
If r > l
1. Find the middle point to divide the array into two halves:
middle m = (l+r)/2
2. Call mergeSort for first half:
Call mergeSort(arr, l, m)
3. Call mergeSort for second half:
Call mergeSort(arr, m+1, r)
4. Merge the two halves sorted in step 2 and 3:
Suthoju Girija Rani – [email protected]
NGIT DSA 2023 UNIT-V Lecture Notes
Call merge(arr, l, m, r)
#include <stdio.h>
#include <stdlib.h>
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
}
else {
arr[k] = R[j];
j++;
}
k++;
}
int m = l + (r - l) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
// main function
void main() {
int n;
Suthoju Girija Rani – [email protected]
NGIT DSA 2023 UNIT-V Lecture Notes
scanf("%d",&n);
int data[n];
for(int i=0;i<n;i++)
{
scanf("%d",&data[i]);
}
mergeSort(data, 0, n - 1);
for (int i = 0; i < n; ++i) {
printf("%d ", data[i]);
}
}
Heap Sort
#include <stdio.h>
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
Suthoju Girija Rani – [email protected]
NGIT DSA 2023 UNIT-V Lecture Notes
*b = temp;
}
void heapify(int arr[], int N, int i)
{
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < N && arr[left] > arr[largest])
largest = left;
if (right < N && arr[right] > arr[largest])
largest = right;
if (largest != i)
{
swap(&arr[i], &arr[largest]);
heapify(arr, N, largest);
}
}
void heapSort(int arr[], int N)
{
int i,temp;
for (i = N / 2 - 1; i >= 0; i--)
heapify(arr, N, i);
for (i = N - 1; i >= 0; i--)
{
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
}
int main()
{
int n,i;
scanf("%d",&n);
int arr[n];
for(i=0;i<n;i++)
scanf("%d",&arr[i]);
heapSort(arr, n);
Suthoju Girija Rani – [email protected]
NGIT DSA 2023 UNIT-V Lecture Notes
for (i = 0; i < n; i++)
printf("%d ", arr[i]);
}
Shell Sort
Shell sort is a highly efficient sorting algorithm and is based on insertion sort algorithm. This
algorithm avoids large shifts as in case of insertion sort, if the smaller value is to the far right
and has to be moved to the far left.
This algorithm uses insertion sort on a widely spread elements, first to sort them and then
sorts the less widely spaced elements. This spacing is termed as interval. This interval is
calculated based on Knuth's formula as −
Knuth's Formula
h=h*3+1
where −
h is interval with initial value 1
This algorithm is quite efficient for medium-sized data sets as its average and worst-case
complexity of this algorithm depends on the gap sequence the best known is Ο(n), where n
is the number of items. And the worst case space complexity is O(n).
We compare values in each sub-list and swap them (if necessary) in the original
array. After this step, the new array should look like this −
We compare and swap the values, if required, in the original array. After this step,
the array should look like this −
Finally, we sort the rest of the array using interval of value 1. Shell sort uses
insertion sort to sort the array.
We see that it required only four swaps to sort the rest of the array.
Algorithm