Assignment 2
Assignment 2
ASSIGNMENT 4:
DATA STRUCTURE
SUBBMITTED BY:
YUSRA GULFAM
SP21-BCS-065
SUBMITTED TO :
SIR DR.IMRAN ALI KHAN
Date:
02/01/23
Graph Data Structure
A graph is a pictorial representation of a set of objects where some pairs
of objects are connected by links. The interconnected objects are
represented by points termed as vertices, and the links that connect the
vertices are called edges.
Incidence Matrix
Adjacency list
Adjacency Matrix
A sequential representation is an adjacency matrix.
It's used to show which nodes are next to one another. I.e.,
is there any connection between nodes in a graph?
Incidence Matrix
In this representation, graph can be represented using a matrix of size
total number of vertices by total number of edges. That means if a graph
with 4 vertices and 6 edges can be represented using a matrix of 4X6
class. In this matrix, rows represents vertices and columns represents
edges. This matrix is filled with either 0 or 1 or -1. Here, 0 represents row
edge is not connected to column vertex, 1 represents row edge is
connected as outgoing edge to column vertex and -1 represents row
edge is connected as incoming edge to column vertex.
Traversal Techniques
Breadth First Search (BFS)
We start from
visiting S (starting node), and
mark it as visited.
3
We then see an unvisited
adjacent node from S. In this
example, we have three
nodes but alphabetically we
choose A, mark it as visited
and enqueue it.
From A we have D as
unvisited adjacent node. We
mark it as visited and
enqueue it.
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.
2
Mark S as visited and put it
onto the stack. Explore any
unvisited adjacent node
from S. We have three nodes
and we can pick any of them.
For this example, we shall
take the node in an
alphabetical order.
3
Mark A as visited and put it
onto the stack. Explore any
unvisited adjacent node from
A. Both S and D are adjacent
to A but we are concerned for
unvisited nodes only.
4
Visit D and mark it as visited
and put onto the stack. Here,
we have B and C nodes,
which are adjacent to D and
both are unvisited. However,
we shall again choose in an
alphabetical order.
We choose B, mark it as
visited and put onto the stack.
Here B does not have any
unvisited adjacent node. So,
we pop B from the stack.
6
We check the stack top for
return to the previous node
and check if it has any
unvisited nodes. Here, we
find D to be on the top of the
stack.
Dijkstra algorithm
1. The very first step is to mark all nodes as unvisited,
2. Mark the picked starting node with a current distance of 0 and the
rest nodes with infinity,
3. Now, fix the starting node as the current node,
4. For the current node, analyse all of its unvisited neighbours and
measure their distances by adding the current distance of the
current node to the weight of the edge that connects the neighbour
node and current node,
5. Compare the recently measured distance with the current distance
assigned to the neighbouring node and make it as the new current
distance of the neighbouring node,
6. After that, consider all of the unvisited neighbours of the current
node, mark the current node as visited,
7. If the destination node has been marked visited then stop, an
algorithm has ended, and
8. Else, choose the unvisited node that is marked with the least
distance, fix it as the new current node, and repeat the process
again from step 4.
import java.util.*;
import java.lang.*;
import java.io.*;
class dijkstra_algo {
min = distance[v];
min_index = v;
return min_index;
}
// Function that implements Dijkstra's algorithm
visited[i] = false;
distance[source] = 0;
visited[u] = true;
// picked vertex.
printSolution(distance, n);
// Driver method
{4,0,11,9,7,0},
{5,11,0,0,3,0},
{0,9,0,0,13,2},
{0,7,3,13,0,6},
{0,0,0,2,6,0}};
int src=0;
t.dijkstra(graph, src);
A 0
B 4
C 5
D 13
E 8
F 14
Prim’s Algorithm
Prim’s Algorithm is a famous greedy algorithm.
It is used for finding the Minimum Spanning Tree (MST) of a given
graph.
To apply Prim’s algorithm, the given graph must be weighted,
connected and undirected.
Step-01:
Randomly choose any vertex.
The vertex connecting to the edge having least weight is usually
selected
.
Step-02:
Find all the edges that connect the tree to new vertices.
Find the least weight edge among those edges and include it in the
existing tree.
If including that edge creates a cycle, then reject that edge and
look for the next least weight edge.
Step-03:
Keep repeating step-02 until all the vertices are included and
Minimum Spanning Tree (MST) is obtained.
Now, you have reached node B. From node B, there are two
possible edges out of which edge BD has the least edge weight
value. So, you will include it in your MST.
From node D, you only have one edge. So, you will include it in
your MST. Further, you have node H, for which you have two
incident edges. Out of those two edges, edge HI has the least
cost, so you will include it in MST structure.
After that, nodes E and C will get included. Now, from node C,
you have two incident edges. Edge CA has the tiniest edge
weight. But its inclusion will create a cycle in a tree structure,
which you cannot allow. Thus, we will discard edge CA as
shown in the image below.
The summation of all the edge weights in MST T(V’, E’) is equal
to 30, which is the least possible edge weight for any possible
spanning tree structure for this particular graph.
import java.util.ArrayList;
• import java.util.Arrays;
• import java.util.List;
• import java.util.Collections;
• import java.util.PriorityQueue;
• import java.util.Comparator;
•
• class NodeCost {
•
• int node; // Adjacent node
• int cost; // Costance/cost to adjacent node
•
• NodeCost (int node, int cost) {
• this.node = node;
• this.cost = cost;
• }
• }
•
• class Prims {
•
• int Find_MST(int source_node, List<List<NodeCost>> graph) {
•
• // Comparator lambda function that enables the priority queue to
store the nodes
• // based on the cost in the ascending order.
• Comparator<NodeCost> NodeCostComparator = (obj1, obj2) -> {
• return obj1.cost - obj2.cost;
• };
•
• // Priority queue stores the object node-cost into the queue with
• // the smallest cost node at the top.
• PriorityQueue<NodeCost> pq = new
PriorityQueue<>(NodeCostComparator);
•
• // The cost of the source node to itself is 0
• pq.add(new NodeCost(source_node, 0));
•
• boolean added[] = new boolean[graph.size()];
• Arrays.fill(added, false);
•
• int mst_cost = 0;
•
• while (!pq.isEmpty()) {
•
• // Select the item <node, cost> with minimum cost
• NodeCost item = pq.peek();
• pq.remove();
•
• int node = item.node;
• int cost = item.cost;
•
• // If the node is node not yet added to the minimum spanning
tree, add it and increment the cost.
• if ( !added[node] ) {
• mst_cost += cost;
• added[node] = true;
•
• // Iterate through all the nodes adjacent to the node taken out
of priority queue.
• // Push only those nodes (node, cost) that are not yet present
in the minumum spanning tree.
• for (NodeCost pair_node_cost : graph.get(node)) {
• int adj_node = pair_node_cost.node;
• if (added[adj_node] == false) {
• pq.add(pair_node_cost);
• }
• }
• }
• }
• return mst_cost;
• }
•
• public static void main(String args[]) {
•
• Prims p = new Prims();
•
• int num_nodes = 6; // Nodes (0, 1, 2, 3, 4, 5)
•
• List<List<NodeCost>> graph_1 = new ArrayList<>(num_nodes);
• for (int i=0; i < num_nodes; i++) {
• graph_1.add(new ArrayList<>());
• }
•
• // Node 0
• Collections.addAll(graph_1.get(0), new NodeCost(1, 4), new
NodeCost(2, 1), new NodeCost(3, 5));
• // Node 1
• Collections.addAll(graph_1.get(1), new NodeCost(0, 4), new
NodeCost(3, 2), new NodeCost(4, 3),
• new NodeCost(5, 3));
• // Node 2
• Collections.addAll(graph_1.get(2), new NodeCost(0, 1), new
NodeCost(3, 2), new NodeCost(4, 8));
• // Node 3
• Collections.addAll(graph_1.get(3), new NodeCost(0, 5), new
NodeCost(1, 2), new NodeCost(2, 2),
• new NodeCost(4, 1));
• // Node 4
• Collections.addAll(graph_1.get(4), new NodeCost(1, 3), new
NodeCost(2, 8), new NodeCost(3, 1),
• new NodeCost(5, 4));
• // Nod
•
• e5
• Collections.addAll(graph_1.get(5), new NodeCost(1, 3), new
NodeCost(4, 4));
•
• // Start adding nodes to minimum spanning tree with 0 as the
souce node
• System.out.println("Cost of the minimum spanning tree in graph
1 : " + p.Find_MST(0, graph_1));
•
• // Outgoing edges from the node:<cost, adjacent_node> in graph
2.
• num_nodes = 7; // Nodes (0, 1, 2, 3, 4, 5, 6)
•
• List<List<NodeCost>> graph_2 = new ArrayList<>(num_nodes);
• for (int i=0; i < num_nodes; i++) {
• graph_2.add(new ArrayList<>());
• }
•
• // Node 0
• Collections.addAll(graph_2.get(0), new NodeCost(1, 1), new
NodeCost(2, 2), new NodeCost(3, 1),
• new NodeCost(4, 1), new NodeCost(5, 2),
new NodeCost(6, 1));
• // Node 1
• Collections.addAll(graph_2.get(1), new NodeCost(0, 1), new
NodeCost(2, 2), new NodeCost(6, 2));
• // Node 2
• Collections.addAll(graph_2.get(2), new NodeCost(0, 2), new
NodeCost(1, 2), new NodeCost(3, 1));
• // Node 3
• Collections.addAll(graph_2.get(3), new NodeCost(0, 1), new
NodeCost(2, 1), new NodeCost(4, 2));
• // Node 4
• Collections.addAll(graph_2.get(4), new NodeCost(0, 1), new
NodeCost(3, 2), new NodeCost(5, 2));
• // Node 5
• Collections.addAll(graph_2.get(5), new NodeCost(0, 2), new
NodeCost(4, 2), new NodeCost(6, 1));
• // Node 6
• Collections.addAll(graph_2.get(6), new NodeCost(0, 1), new
NodeCost(1, 2), new NodeCost(5, 1));
•
•
• // Start adding nodes to minimum spanning tree with 0 as the
souce node
• System.out.println("Cost of the minimum spanning tree in graph
2 : " + p.Find_MST(0, graph_2));
• }
• }
Output
• Cost of the minimum spanning tree in graph 1 : 9
• Cost of the minimum spanning tree in graph 2 : 6
Kruskal's Algorithm
Kruskal's algorithm is a greedy algorithm in graph theory that finds a
minimum spanning tree for a connected weighted graph.
It finds a subset of the edges that forms a tree that includes every vertex,
where the total weight of all the edges in the tree is minimized.
This algorithm is directly based on the MST( minimum spanning tree)
property.
Kruskal's algorithm
It falls under a class of algorithms called greedy algorithms that find the
local optimum in the hopes of finding a global optimum.
We start from the edges with the lowest weight and keep adding edges
until we reach our goal.
2. Take the edge with the lowest weight and add it to the spanning
tree. If adding the edge created a cycle, then reject this edge.
Choose the edge with the least weight, if there are more than 1, choose
anyone
Choose the next shortest edge and add it
Choose the next shortest edge that doesn't create a cycle and add it
Choose the next shortest edge that doesn't create a cycle and add it
import java.util.*;
class Graph {
class Edge implements Comparable<Edge> {
int src, dest, weight;
// Union
class subset {
int parent, rank;
};
// Graph creation
Graph(int v, int e) {
vertices = v;
edges = e;
edge = new Edge[edges];
for (int i = 0; i < e; ++i)
edge[i] = new Edge();
}
G.edge[0].src = 0;
G.edge[0].dest = 1;
G.edge[0].weight = 4;
G.edge[1].src = 0;
G.edge[1].dest = 2;
G.edge[1].weight = 4;
G.edge[2].src = 1;
G.edge[2].dest = 2;
G.edge[2].weight = 2;
G.edge[3].src = 2;
G.edge[3].dest = 3;
G.edge[3].weight = 3;
G.edge[4].src = 2;
G.edge[4].dest = 5;
G.edge[4].weight = 2;
G.edge[5].src = 2;
G.edge[5].dest = 4;
G.edge[5].weight = 4;
G.edge[6].src = 3;
G.edge[6].dest = 4;
G.edge[6].weight = 3;
G.edge[7].src = 5;
G.edge[7].dest = 4;
G.edge[7].weight = 3;
G.KruskalAlgo();
}
}