Data Structures Unit 4
Data Structures Unit 4
Data Structures
R18 CSE/IT II year
By
D. Subhashini
Associate Professor
Department of Computer Science and Engineering
Aurora’s Technological and Research Institute
UNIT IV
Graphs: Graph Implementation Methods, Graph
Traversal Methods.
Sorting: Heap Sort, External Sorting- Model for
external sorting, Merge Sort.
Graph
A graph can be defined as group of vertices and edges that are used to connect these
vertices. A graph can be seen as a cyclic tree, where the vertices (Nodes) maintain any
complex relationship among them instead of having parent child relationship.
Definition
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.
A Graph G(V, E) with 5 vertices (A, B, C, D, E) and six edges ((A,B), (B,C), (C,E), (E,D),
(D,B), (D,A)) is shown in the following figure.
In a directed graph, edges form an ordered pair. Edges represent a specific path from
some vertex A to another vertex B. Node A is called initial node while node B is called
terminal node.
Graph Terminology
Path
A path can be defined as the sequence of nodes that are followed in order to reach some
terminal node V from the initial node U.
Closed Path
A path will be called as closed path if the initial node is same as terminal node. A path
will be closed path if V0=VN.
Simple Path
If all the nodes of the graph are distinct with an exception V 0=VN, then such path P is
called as closed simple path.
Cycle
A cycle can be defined as the path which has no repeated edges or vertices except the
first and last vertices.
Connected Graph
A connected graph is the one in which some path exists between every two vertices (u,
v) in V. There are no isolated nodes in connected graph.
Complete Graph
A complete graph is the one in which every node is connected with all other nodes. A
complete graph contain n(n-1)/2 edges where n is the number of nodes in the graph.
Weighted Graph
In a weighted graph, each edge is assigned with some data such as length or weight. The
weight of an edge e can be given as w(e) which must be a positive (+) value indicating
the cost of traversing the edge.
Digraph
A digraph is a directed graph in which each edge of the graph is associated with some
direction and the traversing can be done only in the specified direction.
Loop
An edge that is associated with the similar end points can be called as Loop.
Adjacent Nodes
If two nodes u and v are connected via an edge e, then the nodes u and v are called as
neighbors or adjacent nodes.
Graph Representation
By Graph representation, we simply mean the technique which is to be used in order to
store some graph into the computer's memory.
There are two ways to store Graph into the computer's memory.
An undirected graph and its adjacency matrix representation is shown in the following
figure.
in the above figure, we can see the mapping among the vertices (A, B, C, D, E) is
represented by using the adjacency matrix which is also shown in the figure.
There exists different adjacency matrices for the directed and undirected graph. In
directed graph, an entry Aij will be 1 only when there is an edge directed from Vi to Vj.
A directed graph and its adjacency matrix representation is shown in the following figure.
The weighted directed graph along with the adjacency matrix representation is shown in
the following figure.
In the linked representation, an adjacency list is used to store the Graph into the
computer's memory. Consider the undirected graph shown in the following figure and
check the adjacency list representation.
An adjacency list is maintained for each node present in the graph which stores the node
value and a pointer to the next adjacent node to the respective node. If all the adjacent
nodes are traversed then store the NULL in the pointer field of last node of the list. The
sum of the lengths of adjacency lists is equal to the twice of the number of edges present
in an undirected graph.
Consider the directed graph shown in the following figure and check the adjacency list
representation of the graph.
In a directed graph, the sum of lengths of all the adjacency lists is equal to the number
of edges present in the graph.
In the case of weighted directed graph, each node contains an extra field that is called
the weight of the node. The adjacency list representation of a directed graph is shown in
the following figure.
Array Length = n
No. of list elements = 2e (undirected graph)
No. of list elements = e (digraph)
As in the example given above, BFS algorithm traverses from A to B to E to F first then
to C and G lastly to D. It employs the following rules.
Rule 1 − Visit the adjacent unvisited vertex. Mark it as visited. Display it. Insert
it in a queue.
Rule 2 − If no adjacent vertex is found, remove the first vertex from the queue.
Rule 3 − Repeat Rule 1 and Rule 2 until the queue is empty.
At this stage, we are left with no unmarked (unvisited) nodes. But as per the algorithm
we keep on dequeuing in order to get all unvisited nodes. When the queue gets emptied,
the program is over.
Here enqueue is a entering a new element into the queue and dequeuer is deleting an
element from the queue.
BFS example2
Let's see how the Breadth First Search algorithm works with an example. We use an
We start from vertex 0, the BFS algorithm starts by putting it in the Visited list and
putting all its adjacent vertices in the stack.
Next, we visit the element at the front of queue i.e. 1 and go to its adjacent nodes.
Vertex 2 has an unvisited adjacent vertex in 4, so we add that to the back of the queue
Only 4 remains in the queue since the only adjacent node of 3 i.e. 0 is already visited.
We visit it.
Visit last remaining item in the stack to check if it has unvisited neighbors
Since the queue is empty, we have completed the Breadth First Traversal of the graph.
#include<stdio.h>
#include<conio.h>
int a[20][20],q[20],visited[20],n,i,j,f=0,r=-1;
void bfs(int v) {
for (i=1;i<=n;i++)
if(a[v][i] && !visited[i])
q[++r]=i;
if(f<=r) {
visited[q[f]]=1;
bfs(q[f++]);
}
}
void main() {
int v;
clrscr();
printf("\n Enter the number of vertices:");
scanf("%d",&n);
for (i=1;i<=n;i++) {
q[i]=0;
visited[i]=0;
}
printf("\n Enter graph data in matrix form:\n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
scanf("%d",&a[i][j]);
printf("\n Enter the starting vertex:");
scanf("%d",&v);
bfs(v);
printf("\n The node which are reachable are:\n");
for (i=1;i<=n;i++)
if(visited[i])
printf("%d\t",i);
else
printf("\n %d Not visited using bfs", i);
getch();
}
As C does not have any unvisited adjacent node so we keep popping the stack until we
find a node that has an unvisited adjacent node. In this case, there's none and we keep
popping until the stack is empty.
As the DFS procedure uses stack, we can easily implement it using recursion.
Algorithm:
dfs(v)
{
Label vertex v as reached.
for (each unreached vertex u
adjacenct from v)
dfs(u);
}
We start from vertex 0, the DFS algorithm starts by putting it in the Visited list and
Next, we visit the element at the top of stack i.e. 1 and go to its adjacent nodes. Since
Vertex 2 has an unvisited adjacent vertex in 4, so we add that to the top of the stack
Vertex 2 has an unvisited adjacent vertex in 4, so we add that to the top of the stack and visit it.
Vertex 2 has an unvisited adjacent vertex in 4, so we add that to the top of the stack and visit it.
After we visit the last element 3, it doesn't have any unvisited adjacent nodes, so we
After we visit the last element 3, it doesn't have any unvisited adjacent nodes, so we
void dfs(int v)
{
visited[i]=1;
for (i=1;i<=n;i++)
if(a[v][i] && !visited[i])
dfs(i);
}
void main()
{
int v;
clrscr();
printf("\n Enter the number of vertices:");
scanf("%d",&n);
for (i=1;i<=n;i++)
visited[i]=0;
printf("\n Enter graph data in matrix form:\n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
scanf("%d",&a[i][j]);
printf("\n Enter the starting vertex:");
scanf("%d",&v);
dfs(v);
printf("\n The node which are reachable are:\n");
for (i=1;i<=n;i++)
if(visited[i])
printf("%d\t",i);
getch();
}
Max-Heap − Where the value of the root node is greater than or equal to either of its
children.
Both trees are constructed using the same input and order of arrival.
Step 2:
Step 3:
Step 4:
Step 5:
Step 6:
Step 7:
Step 8:
Step 9:
Step 10:
Step 11:
Step 12:
Step 13:
Step 14:
#include <stdio.h>
void main()
{
int a[10],n,i;
printf("Enter no. of elements");
scanf("%d",&n);
printf("\n enter data to be sored ..");
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
heapsort(a,n);
printf("sorted data:\n");
for (i=1;i<=n;i++)
printf(" %d",a[i]);
}
j = 2*j;
}
a[j/2] = item;
}
Categories of Sorting
The techniques of sorting can be divided into two categories. These are:
Internal Sorting
External Sorting
Internal Sorting: If all the data that is to be sorted can be adjusted at a time in the main
memory, the internal sorting method is being performed.
External Sorting: When the data that is to be sorted cannot be accommodated in the
memory at the same time and some has to be kept in auxiliary memory such as hard
disk, floppy disk, magnetic tapes etc, then external sorting methods are performed.
The length of time spent by the programmer in programming a specific sorting program
Amount of machine time necessary for running the program
The amount of memory necessary for running the program
Merge sort
Merge sort is the algorithm which follows divide and conquer approach. Consider an
array A of n number of elements. The algorithm processes the elements in 3 steps.
2. Conquer means sort the two sub-arrays recursively using the merge sort.
3. Combine the sub-arrays to form a single final sorted array maintaining the
ordering of the array.
The main idea behind merge sort is that, the short list takes less time to be sorted.
Complexity
Example :
Consider the following array of 7 elements. Sort the array by using merge sort.
C Program
#include<stdio.h>
void mergeSort(int[],int,int);
void merge(int[],int,int,int);
void main ()
{
int n,a[10];
int i;
printf("Enter no. of elements");
scanf("%d",&n);
printf("\n enter data to be sored ..");
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
mergeSort(a,0,n);
printf("printing the sorted elements");
for(i=0;i<n;i++)
printf("\n%d\n",a[i]);
}
if(i>mid)
{
while(j<=end)
{
temp[index] = a[j];
index++;
j++;
}
}
else
{
while(i<=mid)
{
temp[index] = a[i];
index++;
i++;
}
}
k = beg;
while(k<index)
{
a[k]=temp[k];
k++;
}
}