style: format code (#4212)

close #4204
This commit is contained in:
acbin
2023-06-09 18:52:05 +08:00
committed by GitHub
parent ad03086f54
commit 00282efd8b
521 changed files with 5233 additions and 7309 deletions

View File

@ -1,5 +1,5 @@
/*
Time Complexity = O(E), where E is equal to the number of edges
Time Complexity = O(E), where E is equal to the number of edges
*/
package com.thealgorithms.datastructures.graphs;
@ -64,13 +64,10 @@ public class A_Star {
private int distance; // distance advanced so far.
private ArrayList<Integer> path; // list of visited nodes in this path.
private int estimated; // heuristic value associated to the last node od the path (current node).
private int
estimated; // heuristic value associated to the last node od the path (current node).
public PathAndDistance(
int distance,
ArrayList<Integer> path,
int estimated
) {
public PathAndDistance(int distance, ArrayList<Integer> path, int estimated) {
this.distance = distance;
this.path = path;
this.estimated = estimated;
@ -90,25 +87,16 @@ public class A_Star {
private void printSolution() {
if (this.path != null) {
System.out.println(
"Optimal path: " +
this.path +
", distance: " +
this.distance
);
System.out.println("Optimal path: " + this.path + ", distance: " + this.distance);
} else {
System.out.println(
"There is no path available to connect the points"
);
System.out.println("There is no path available to connect the points");
}
}
}
private static void initializeGraph(Graph graph, ArrayList<Integer> data) {
for (int i = 0; i < data.size(); i += 4) {
graph.addEdge(
new Edge(data.get(i), data.get(i + 1), data.get(i + 2))
);
graph.addEdge(new Edge(data.get(i), data.get(i + 1), data.get(i + 2)));
}
/*
.x. node
@ -165,123 +153,24 @@ public class A_Star {
};
Graph graph = new Graph(20);
ArrayList<Integer> graphData = new ArrayList<>(
Arrays.asList(
0,
19,
75,
null,
0,
15,
140,
null,
0,
16,
118,
null,
19,
12,
71,
null,
12,
15,
151,
null,
16,
9,
111,
null,
9,
10,
70,
null,
10,
3,
75,
null,
3,
2,
120,
null,
2,
14,
146,
null,
2,
13,
138,
null,
2,
6,
115,
null,
15,
14,
80,
null,
15,
5,
99,
null,
14,
13,
97,
null,
5,
1,
211,
null,
13,
1,
101,
null,
6,
1,
160,
null,
1,
17,
85,
null,
17,
7,
98,
null,
7,
4,
86,
null,
17,
18,
142,
null,
18,
8,
92,
null,
8,
11,
87
)
);
ArrayList<Integer> graphData = new ArrayList<>(Arrays.asList(0, 19, 75, null, 0, 15, 140,
null, 0, 16, 118, null, 19, 12, 71, null, 12, 15, 151, null, 16, 9, 111, null, 9, 10,
70, null, 10, 3, 75, null, 3, 2, 120, null, 2, 14, 146, null, 2, 13, 138, null, 2, 6,
115, null, 15, 14, 80, null, 15, 5, 99, null, 14, 13, 97, null, 5, 1, 211, null, 13, 1,
101, null, 6, 1, 160, null, 1, 17, 85, null, 17, 7, 98, null, 7, 4, 86, null, 17, 18,
142, null, 18, 8, 92, null, 8, 11, 87));
initializeGraph(graph, graphData);
PathAndDistance solution = aStar(3, 1, graph, heuristic);
solution.printSolution();
}
public static PathAndDistance aStar(
int from,
int to,
Graph graph,
int[] heuristic
) {
public static PathAndDistance aStar(int from, int to, Graph graph, int[] heuristic) {
// nodes are prioritised by the less value of the current distance of their paths, and the
// estimated value
// given by the heuristic function to reach the destination point from the current point.
PriorityQueue<PathAndDistance> queue = new PriorityQueue<>(
Comparator.comparingInt(a -> (a.getDistance() + a.getEstimated()))
);
Comparator.comparingInt(a -> (a.getDistance() + a.getEstimated())));
// dummy data to start the algorithm from the beginning point
queue.add(new PathAndDistance(0, new ArrayList<>(List.of(from)), 0));
@ -290,34 +179,25 @@ public class A_Star {
PathAndDistance currentData = new PathAndDistance(-1, null, -1);
while (!queue.isEmpty() && !solutionFound) {
currentData = queue.poll(); // first in the queue, best node so keep exploring.
int currentPosition = currentData
.getPath()
.get(currentData.getPath().size() - 1); // current node.
int currentPosition
= currentData.getPath().get(currentData.getPath().size() - 1); // current node.
if (currentPosition == to) {
solutionFound = true;
} else {
for (Edge edge : graph.getNeighbours(currentPosition)) {
if (!currentData.getPath().contains(edge.getTo())) { // Avoid Cycles
ArrayList<Integer> updatedPath = new ArrayList<>(
currentData.getPath()
);
updatedPath.add(edge.getTo()); // Add the new node to the path, update the distance,
ArrayList<Integer> updatedPath = new ArrayList<>(currentData.getPath());
updatedPath.add(
edge.getTo()); // Add the new node to the path, update the distance,
// and the heuristic function value associated to that path.
queue.add(
new PathAndDistance(
currentData.getDistance() + edge.getWeight(),
updatedPath,
heuristic[edge.getTo()]
)
);
queue.add(new PathAndDistance(currentData.getDistance() + edge.getWeight(),
updatedPath, heuristic[edge.getTo()]));
}
}
}
}
return (solutionFound)
? currentData
: new PathAndDistance(-1, null, -1);
// Out of while loop, if there is a solution, the current Data stores the optimal path, and its
// distance
return (solutionFound) ? currentData : new PathAndDistance(-1, null, -1);
// Out of while loop, if there is a solution, the current Data stores the optimal path, and
// its distance
}
}

View File

@ -2,8 +2,10 @@ package com.thealgorithms.datastructures.graphs;
import java.util.*;
class BellmanFord /*Implementation of Bellman ford to detect negative cycles. Graph accepts inputs in form of edges which have
start vertex, end vertex and weights. Vertices should be labelled with a number between 0 and total number of vertices-1,both inclusive*/{
class BellmanFord /*Implementation of Bellman ford to detect negative cycles. Graph accepts inputs
in form of edges which have start vertex, end vertex and weights. Vertices should be labelled with a
number between 0 and total number of vertices-1,both inclusive*/
{
int vertex, edge;
private Edge[] edges;
@ -49,7 +51,8 @@ start vertex, end vertex and weights. Vertices should be labelled with a number
obj.go();
}
public void go() { // shows distance to all vertices // Interactive run for understanding the class first time. Assumes source vertex is 0 and
public void go() { // shows distance to all vertices // Interactive run for understanding the
// class first time. Assumes source vertex is 0 and
Scanner sc = new Scanner(System.in); // Grab scanner object for user input
int i, v, e, u, ve, w, j, neg = 0;
System.out.println("Enter no. of vertices and edges please");
@ -63,7 +66,8 @@ start vertex, end vertex and weights. Vertices should be labelled with a number
w = sc.nextInt();
arr[i] = new Edge(u, ve, w);
}
int[] dist = new int[v]; // Distance array for holding the finalized shortest path distance between source
int[] dist = new int[v]; // Distance array for holding the finalized shortest path distance
// between source
// and all vertices
int[] p = new int[v]; // Parent array for holding the paths
for (i = 0; i < v; i++) {
@ -73,10 +77,8 @@ start vertex, end vertex and weights. Vertices should be labelled with a number
p[0] = -1;
for (i = 0; i < v - 1; i++) {
for (j = 0; j < e; j++) {
if (
dist[arr[j].u] != Integer.MAX_VALUE &&
dist[arr[j].v] > dist[arr[j].u] + arr[j].w
) {
if (dist[arr[j].u] != Integer.MAX_VALUE
&& dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
dist[arr[j].v] = dist[arr[j].u] + arr[j].w; // Update
p[arr[j].v] = arr[j].u;
}
@ -84,10 +86,7 @@ start vertex, end vertex and weights. Vertices should be labelled with a number
}
// Final cycle for negative checking
for (j = 0; j < e; j++) {
if (
dist[arr[j].u] != Integer.MAX_VALUE &&
dist[arr[j].v] > dist[arr[j].u] + arr[j].w
) {
if (dist[arr[j].u] != Integer.MAX_VALUE && dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
neg = 1;
System.out.println("Negative cycle");
break;
@ -113,9 +112,13 @@ start vertex, end vertex and weights. Vertices should be labelled with a number
* @param end Ending vertex
* @param Edge Array of edges
*/
public void show(int source, int end, Edge[] arr) { // be created by using addEdge() method and passed by calling getEdgeArray() method // Just shows results of computation, if graph is passed to it. The graph should
public void show(int source, int end,
Edge[] arr) { // be created by using addEdge() method and passed by calling getEdgeArray()
// method // Just shows results of computation, if graph is passed to it. The
// graph should
int i, j, v = vertex, e = edge, neg = 0;
double[] dist = new double[v]; // Distance array for holding the finalized shortest path distance between source
double[] dist = new double[v]; // Distance array for holding the finalized shortest path
// distance between source
// and all vertices
int[] p = new int[v]; // Parent array for holding the paths
for (i = 0; i < v; i++) {
@ -125,10 +128,8 @@ start vertex, end vertex and weights. Vertices should be labelled with a number
p[source] = -1;
for (i = 0; i < v - 1; i++) {
for (j = 0; j < e; j++) {
if (
(int) dist[arr[j].u] != Integer.MAX_VALUE &&
dist[arr[j].v] > dist[arr[j].u] + arr[j].w
) {
if ((int) dist[arr[j].u] != Integer.MAX_VALUE
&& dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
dist[arr[j].v] = dist[arr[j].u] + arr[j].w; // Update
p[arr[j].v] = arr[j].u;
}
@ -136,10 +137,8 @@ start vertex, end vertex and weights. Vertices should be labelled with a number
}
// Final cycle for negative checking
for (j = 0; j < e; j++) {
if (
(int) dist[arr[j].u] != Integer.MAX_VALUE &&
dist[arr[j].v] > dist[arr[j].u] + arr[j].w
) {
if ((int) dist[arr[j].u] != Integer.MAX_VALUE
&& dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
neg = 1;
System.out.println("Negative cycle");
break;

View File

@ -17,11 +17,7 @@ import java.util.Arrays;
public class BipartiteGrapfDFS {
private static boolean bipartite(
int V,
ArrayList<ArrayList<Integer>> adj,
int[] color,
int node
) {
int V, ArrayList<ArrayList<Integer>> adj, int[] color, int node) {
if (color[node] == -1) {
color[node] = 1;
}
@ -38,10 +34,7 @@ public class BipartiteGrapfDFS {
return true;
}
public static boolean isBipartite(
int V,
ArrayList<ArrayList<Integer>> adj
) {
public static boolean isBipartite(int V, ArrayList<ArrayList<Integer>> adj) {
// Code here
int[] color = new int[V + 1];
Arrays.fill(color, -1);
@ -57,9 +50,7 @@ public class BipartiteGrapfDFS {
}
public static void main(String[] args) throws IOException {
BufferedReader read = new BufferedReader(
new InputStreamReader(System.in)
);
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(read.readLine().trim());
while (t-- > 0) {
String[] S = read.readLine().trim().split(" ");

View File

@ -137,11 +137,7 @@ public class ConnectedComponent {
graphInts.addEdge(8, 10);
graphInts.addEdge(10, 8);
System.out.println(
"Amount of different char-graphs: " + graphChars.countGraphs()
);
System.out.println(
"Amount of different int-graphs: " + graphInts.countGraphs()
);
System.out.println("Amount of different char-graphs: " + graphChars.countGraphs());
System.out.println("Amount of different int-graphs: " + graphInts.countGraphs());
}
}

View File

@ -24,9 +24,7 @@ class Cycle {
visited[i] = false;
}
System.out.println(
"Enter the details of each edges <Start Node> <End Node>"
);
System.out.println("Enter the details of each edges <Start Node> <End Node>");
for (int i = 0; i < edges; i++) {
int start, end;

View File

@ -1,6 +1,6 @@
/*
Refer https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/
for better understanding
for better understanding
*/
package com.thealgorithms.datastructures.graphs;
@ -45,12 +45,8 @@ class dijkstras {
Set[u] = true;
for (int v = 0; v < k; v++) {
if (
!Set[v] &&
graph[u][v] != 0 &&
dist[u] != Integer.MAX_VALUE &&
dist[u] + graph[u][v] < dist[v]
) {
if (!Set[v] && graph[u][v] != 0 && dist[u] != Integer.MAX_VALUE
&& dist[u] + graph[u][v] < dist[v]) {
dist[v] = dist[u] + graph[u][v];
}
}
@ -61,23 +57,23 @@ class dijkstras {
public static void main(String[] args) {
int[][] graph = new int[][] {
{ 0, 4, 0, 0, 0, 0, 0, 8, 0 },
{ 4, 0, 8, 0, 0, 0, 0, 11, 0 },
{ 0, 8, 0, 7, 0, 4, 0, 0, 2 },
{ 0, 0, 7, 0, 9, 14, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 10, 0, 0, 0 },
{ 0, 0, 4, 14, 10, 0, 2, 0, 0 },
{ 0, 0, 0, 0, 0, 2, 0, 1, 6 },
{ 8, 11, 0, 0, 0, 0, 1, 0, 7 },
{ 0, 0, 2, 0, 0, 0, 6, 7, 0 },
{0, 4, 0, 0, 0, 0, 0, 8, 0},
{4, 0, 8, 0, 0, 0, 0, 11, 0},
{0, 8, 0, 7, 0, 4, 0, 0, 2},
{0, 0, 7, 0, 9, 14, 0, 0, 0},
{0, 0, 0, 9, 0, 10, 0, 0, 0},
{0, 0, 4, 14, 10, 0, 2, 0, 0},
{0, 0, 0, 0, 0, 2, 0, 1, 6},
{8, 11, 0, 0, 0, 0, 1, 0, 7},
{0, 0, 2, 0, 0, 0, 6, 7, 0},
};
dijkstras t = new dijkstras();
t.dijkstra(graph, 0);
} //main
} //djikstras
} // main
} // djikstras
/*
OUTPUT :
Vertex Distance
Vertex Distance
0 0
1 4
2 12

View File

@ -9,42 +9,32 @@ public class FloydWarshall {
public static final int INFINITY = 999;
public FloydWarshall(int numberofvertices) {
DistanceMatrix = new int[numberofvertices + 1][numberofvertices + 1]; // stores the value of distance from all the possible path form the source
DistanceMatrix = new int[numberofvertices + 1][numberofvertices
+ 1]; // stores the value of distance from all the possible path form the source
// vertex to destination vertex
// The matrix is initialized with 0's by default
this.numberofvertices = numberofvertices;
}
public void floydwarshall(int[][] AdjacencyMatrix) { // calculates all the distances from source to destination vertex
public void floydwarshall(
int[][] AdjacencyMatrix) { // calculates all the distances from source to destination vertex
for (int source = 1; source <= numberofvertices; source++) {
for (
int destination = 1;
destination <= numberofvertices;
destination++
) {
DistanceMatrix[source][destination] =
AdjacencyMatrix[source][destination];
for (int destination = 1; destination <= numberofvertices; destination++) {
DistanceMatrix[source][destination] = AdjacencyMatrix[source][destination];
}
}
for (
int intermediate = 1;
intermediate <= numberofvertices;
intermediate++
) {
for (int intermediate = 1; intermediate <= numberofvertices; intermediate++) {
for (int source = 1; source <= numberofvertices; source++) {
for (
int destination = 1;
destination <= numberofvertices;
destination++
) {
if (
DistanceMatrix[source][intermediate] +
DistanceMatrix[intermediate][destination] <
DistanceMatrix[source][destination]
) { // calculated distance it get replaced as new shortest distance // if the new distance calculated is less then the earlier shortest
DistanceMatrix[source][destination] =
DistanceMatrix[source][intermediate] +
DistanceMatrix[intermediate][destination];
for (int destination = 1; destination <= numberofvertices; destination++) {
if (DistanceMatrix[source][intermediate]
+ DistanceMatrix[intermediate][destination]
< DistanceMatrix[source]
[destination]) { // calculated distance it get replaced as
// new shortest distance // if the new
// distance calculated is less then the
// earlier shortest
DistanceMatrix[source][destination] = DistanceMatrix[source][intermediate]
+ DistanceMatrix[intermediate][destination];
}
}
}
@ -55,11 +45,7 @@ public class FloydWarshall {
System.out.println();
for (int source = 1; source <= numberofvertices; source++) {
System.out.print(source + "\t");
for (
int destination = 1;
destination <= numberofvertices;
destination++
) {
for (int destination = 1; destination <= numberofvertices; destination++) {
System.out.print(DistanceMatrix[source][destination] + "\t");
}
System.out.println();
@ -70,15 +56,10 @@ public class FloydWarshall {
Scanner scan = new Scanner(System.in);
System.out.println("Enter the number of vertices");
int numberOfVertices = scan.nextInt();
int[][] adjacencyMatrix = new int[numberOfVertices +
1][numberOfVertices + 1];
int[][] adjacencyMatrix = new int[numberOfVertices + 1][numberOfVertices + 1];
System.out.println("Enter the Weighted Matrix for the graph");
for (int source = 1; source <= numberOfVertices; source++) {
for (
int destination = 1;
destination <= numberOfVertices;
destination++
) {
for (int destination = 1; destination <= numberOfVertices; destination++) {
adjacencyMatrix[source][destination] = scan.nextInt();
if (source == destination) {
adjacencyMatrix[source][destination] = 0;

View File

@ -21,7 +21,7 @@ public class HamiltonianCycle {
this.V = graph.length;
this.cycle = new int[this.V + 1];
//Initialize path array with -1 value
// Initialize path array with -1 value
for (int i = 0; i < this.cycle.length; i++) {
this.cycle[i] = -1;
}
@ -41,13 +41,15 @@ public class HamiltonianCycle {
return cycle;
}
/** function to find paths recursively
/**
* function to find paths recursively
* Find paths recursively from given vertex
* @param vertex Vertex from which path is to be found
* @returns true if path is found false otherwise
*/
public boolean isPathFound(int vertex) {
boolean isLastVertexConnectedToStart = this.graph[vertex][0] == 1 && this.pathCount == this.V;
boolean isLastVertexConnectedToStart
= this.graph[vertex][0] == 1 && this.pathCount == this.V;
if (isLastVertexConnectedToStart) {
return true;
}
@ -83,7 +85,8 @@ public class HamiltonianCycle {
return false;
}
/** function to check if path is already selected
/**
* function to check if path is already selected
* Check if path is already selected
* @param vertex Starting vertex
*/

View File

@ -133,7 +133,7 @@ class TopologicalSort<E extends Comparable<E>> {
public class KahnsAlgorithm {
public static void main(String[] args) {
//Graph definition and initialization
// Graph definition and initialization
AdjacencyList<String> graph = new AdjacencyList<>();
graph.addEdge("a", "b");
graph.addEdge("c", "a");
@ -144,7 +144,7 @@ public class KahnsAlgorithm {
TopologicalSort<String> topSort = new TopologicalSort<>(graph);
//Printing the order
// Printing the order
for (String s : topSort.topSortOrder()) {
System.out.print(s + " ");
}

View File

@ -7,17 +7,18 @@ import java.util.Stack;
/**
* Java program that implements Kosaraju Algorithm.
* @author Shivanagouda S A (https://github.com/shivu2002a)
*
*
*/
/**
* Kosaraju algorithm is a linear time algorithm to find the strongly connected components of a
directed graph, which, from here onwards will be referred by SCC. It leverages the fact that the transpose
graph (same graph with all the edges reversed) has exactly the same SCCs as the original graph.
* A graph is said to be strongly connected if every vertex is reachable from every other vertex.
The SCCs of a directed graph form a partition into subgraphs that are themselves strongly connected.
Single node is always a SCC.
* Kosaraju algorithm is a linear time algorithm to find the strongly connected components of a
directed graph, which, from here onwards will be referred by SCC. It leverages the fact that the
transpose graph (same graph with all the edges reversed) has exactly the same SCCs as the original
graph.
* A graph is said to be strongly connected if every vertex is reachable from every other vertex.
The SCCs of a directed graph form a partition into subgraphs that are themselves strongly
connected. Single node is always a SCC.
* Example:
@ -26,19 +27,20 @@ import java.util.Stack;
| / | \ /
| / | \ /
v / v \ /
1 5 --> 6
1 5 --> 6
For the above graph, the SCC list goes as follows:
0, 1, 2
0, 1, 2
3
4, 5, 6
7
We can also see that order of the nodes in an SCC doesn't matter since they are in cycle.
{@summary}
* Kosaraju Algorithm:
1. Perform DFS traversal of the graph. Push node to stack before returning. This gives edges sorted by lowest finish time.
* Kosaraju Algorithm:
1. Perform DFS traversal of the graph. Push node to stack before returning. This gives edges
sorted by lowest finish time.
2. Find the transpose graph by reversing the edges.
3. Pop nodes one by one from the stack and again to DFS on the modified graph.
@ -48,7 +50,7 @@ import java.util.Stack;
| / | \ /
| / | \ /
| v | v v
1 5 <--- 6
1 5 <--- 6
We can observe that this graph has the same SCC as that of original graph.
@ -59,33 +61,33 @@ public class Kosaraju {
// Sort edges according to lowest finish time
Stack<Integer> stack = new Stack<Integer>();
//Store each component
// Store each component
private List<Integer> scc = new ArrayList<>();
//All the strongly connected components
// All the strongly connected components
private List<List<Integer>> sccsList = new ArrayList<>();
/**
*
*
* @param v Node count
* @param list Adjacency list of graph
* @return List of SCCs
*/
public List<List<Integer>> kosaraju(int v, List<List<Integer>> list){
public List<List<Integer>> kosaraju(int v, List<List<Integer>> list) {
sortEdgesByLowestFinishTime(v, list);
List<List<Integer>> transposeGraph = createTransposeMatrix(v, list);
findStronglyConnectedComponents(v, transposeGraph);
return sccsList;
}
private void sortEdgesByLowestFinishTime(int v, List<List<Integer>> list){
private void sortEdgesByLowestFinishTime(int v, List<List<Integer>> list) {
int[] vis = new int[v];
for (int i = 0; i < v; i++) {
if(vis[i] == 0){
if (vis[i] == 0) {
dfs(i, vis, list);
}
}
@ -105,15 +107,15 @@ public class Kosaraju {
}
/**
*
*
* @param v Node count
* @param transposeGraph Transpose of the given adjacency list
*/
public void findStronglyConnectedComponents(int v, List<List<Integer>> transposeGraph){
public void findStronglyConnectedComponents(int v, List<List<Integer>> transposeGraph) {
int[] vis = new int[v];
while (!stack.isEmpty()) {
var node = stack.pop();
if(vis[node] == 0){
if (vis[node] == 0) {
dfs2(node, vis, transposeGraph);
sccsList.add(scc);
scc = new ArrayList<>();
@ -121,24 +123,21 @@ public class Kosaraju {
}
}
//Dfs to store the nodes in order of lowest finish time
private void dfs(int node, int[] vis, List<List<Integer>> list){
// Dfs to store the nodes in order of lowest finish time
private void dfs(int node, int[] vis, List<List<Integer>> list) {
vis[node] = 1;
for(Integer neighbour : list.get(node)){
if(vis[neighbour] == 0)
dfs(neighbour, vis, list);
for (Integer neighbour : list.get(node)) {
if (vis[neighbour] == 0) dfs(neighbour, vis, list);
}
stack.push(node);
}
//Dfs to find all the nodes of each strongly connected component
private void dfs2(int node, int[] vis, List<List<Integer>> list){
// Dfs to find all the nodes of each strongly connected component
private void dfs2(int node, int[] vis, List<List<Integer>> list) {
vis[node] = 1;
for(Integer neighbour : list.get(node)){
if(vis[neighbour] == 0)
dfs2(neighbour, vis, list);
for (Integer neighbour : list.get(node)) {
if (vis[neighbour] == 0) dfs2(neighbour, vis, list);
}
scc.add(node);
}
}

View File

@ -15,8 +15,8 @@ import java.util.PriorityQueue;
public class Kruskal {
// Complexity: O(E log V) time, where E is the number of edges in the graph and V is the number of
// vertices
// Complexity: O(E log V) time, where E is the number of edges in the graph and V is the number
// of vertices
private static class Edge {
private int from;
@ -30,12 +30,7 @@ public class Kruskal {
}
}
private static void addEdge(
HashSet<Edge>[] graph,
int from,
int to,
int weight
) {
private static void addEdge(HashSet<Edge>[] graph, int from, int to, int weight) {
graph[from].add(new Edge(from, to, weight));
}
@ -58,9 +53,7 @@ public class Kruskal {
System.out.println("Initial Graph: ");
for (int i = 0; i < graph.length; i++) {
for (Edge edge : graph[i]) {
System.out.println(
i + " <-- weight " + edge.weight + " --> " + edge.to
);
System.out.println(i + " <-- weight " + edge.weight + " --> " + edge.to);
}
}
@ -70,9 +63,7 @@ public class Kruskal {
System.out.println("\nMinimal Graph: ");
for (int i = 0; i < solGraph.length; i++) {
for (Edge edge : solGraph[i]) {
System.out.println(
i + " <-- weight " + edge.weight + " --> " + edge.to
);
System.out.println(i + " <-- weight " + edge.weight + " --> " + edge.to);
}
}
}
@ -83,9 +74,8 @@ public class Kruskal {
// captain of i, stores the set with all the connected nodes to i
HashSet<Integer>[] connectedGroups = new HashSet[nodes];
HashSet<Edge>[] minGraph = new HashSet[nodes];
PriorityQueue<Edge> edges = new PriorityQueue<>(
(Comparator.comparingInt(edge -> edge.weight))
);
PriorityQueue<Edge> edges
= new PriorityQueue<>((Comparator.comparingInt(edge -> edge.weight)));
for (int i = 0; i < nodes; i++) {
minGraph[i] = new HashSet<>();
connectedGroups[i] = new HashSet<>();
@ -98,18 +88,12 @@ public class Kruskal {
while (connectedElements != nodes && !edges.isEmpty()) {
Edge edge = edges.poll();
// This if avoids cycles
if (
!connectedGroups[captain[edge.from]].contains(edge.to) &&
!connectedGroups[captain[edge.to]].contains(edge.from)
) {
if (!connectedGroups[captain[edge.from]].contains(edge.to)
&& !connectedGroups[captain[edge.to]].contains(edge.from)) {
// merge sets of the captains of each point connected by the edge
connectedGroups[captain[edge.from]].addAll(
connectedGroups[captain[edge.to]]
);
connectedGroups[captain[edge.from]].addAll(connectedGroups[captain[edge.to]]);
// update captains of the elements merged
connectedGroups[captain[edge.from]].forEach(i ->
captain[i] = captain[edge.from]
);
connectedGroups[captain[edge.from]].forEach(i -> captain[i] = captain[edge.from]);
// add Edge to minimal graph
addEdge(minGraph, edge.from, edge.to, edge.weight);
// count how many elements have been merged

View File

@ -71,9 +71,7 @@ class AdjacencyMatrixGraph {
public AdjacencyMatrixGraph(int givenNumberOfVertices) {
this.setNumberOfVertices(givenNumberOfVertices);
this.setNumberOfEdges(0);
this.setAdjacency(
new int[givenNumberOfVertices][givenNumberOfVertices]
);
this.setAdjacency(new int[givenNumberOfVertices][givenNumberOfVertices]);
for (int i = 0; i < givenNumberOfVertices; i++) {
for (int j = 0; j < givenNumberOfVertices; j++) {
this.adjacency()[i][j] = AdjacencyMatrixGraph.EDGE_NONE;
@ -247,11 +245,7 @@ class AdjacencyMatrixGraph {
* has been visited
* @param orderList the list to add vertices to as they are visited
*/
private void depthFirstOrder(
int currentVertex,
boolean[] visited,
List<Integer> orderList
) {
private void depthFirstOrder(int currentVertex, boolean[] visited, List<Integer> orderList) {
// If this vertex has already been visited, do nothing and return
if (visited[currentVertex]) {
return;
@ -264,11 +258,9 @@ class AdjacencyMatrixGraph {
// Get the adjacency array for this vertex
int[] adjacent = _adjacency[currentVertex];
for (
int i = 0;
i < adjacent.length;
i++
) { // we are considering exploring, recurse on it // If an edge exists between the currentVertex and the vertex
for (int i = 0; i < adjacent.length;
i++) { // we are considering exploring, recurse on it // If an edge exists between the
// currentVertex and the vertex
if (adjacent[i] == AdjacencyMatrixGraph.EDGE_EXIST) {
depthFirstOrder(i, visited, orderList);
}
@ -317,11 +309,9 @@ class AdjacencyMatrixGraph {
// Get the adjacency array for the currentVertex and
// check each node
int[] adjacent = _adjacency[currentVertex];
for (
int vertex = 0;
vertex < adjacent.length;
vertex++
) { // vertex we are considering exploring, we add it to the queue // If an edge exists between the current vertex and the
for (int vertex = 0; vertex < adjacent.length;
vertex++) { // vertex we are considering exploring, we add it to the queue // If an
// edge exists between the current vertex and the
if (adjacent[vertex] == AdjacencyMatrixGraph.EDGE_EXIST) {
queue.add(vertex);
}

View File

@ -31,9 +31,7 @@ class PrimMST {
void printMST(int[] parent, int n, int[][] graph) {
System.out.println("Edge Weight");
for (int i = 1; i < V; i++) {
System.out.println(
parent[i] + " - " + i + " " + graph[i][parent[i]]
);
System.out.println(parent[i] + " - " + i + " " + graph[i][parent[i]]);
}
}
@ -72,17 +70,12 @@ class PrimMST {
// Update key value and parent index of the adjacent
// vertices of the picked vertex. Consider only those
// vertices which are not yet included in MST
for (
int v = 0;
v < V;
v++
) // Update the key only if graph[u][v] is smaller than key[v] // mstSet[v] is false for vertices not yet included in MST // graph[u][v] is non zero only for adjacent vertices of m
for (int v = 0; v < V;
v++) // Update the key only if graph[u][v] is smaller than key[v] // mstSet[v] is
// false for vertices not yet included in MST // graph[u][v] is non zero only
// for adjacent vertices of m
{
if (
graph[u][v] != 0 &&
!mstSet[v] &&
graph[u][v] < key[v]
) {
if (graph[u][v] != 0 && !mstSet[v] && graph[u][v] < key[v]) {
parent[v] = u;
key[v] = graph[u][v];
}
@ -104,11 +97,11 @@ class PrimMST {
9 */
PrimMST t = new PrimMST();
int[][] graph = new int[][] {
{ 0, 2, 0, 6, 0 },
{ 2, 0, 3, 8, 5 },
{ 0, 3, 0, 0, 7 },
{ 6, 8, 0, 0, 9 },
{ 0, 5, 7, 9, 0 },
{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0},
};
// Print the solution

View File

@ -8,16 +8,16 @@ import java.util.Stack;
/**
* Java program that implements Tarjan's Algorithm.
* @author Shivanagouda S A (https://github.com/shivu2002a)
*
*
*/
/**
* Tarjan's algorithm is a linear time algorithm to find the strongly connected components of a
directed graph, which, from here onwards will be referred as SCC.
* A graph is said to be strongly connected if every vertex is reachable from every other vertex.
The SCCs of a directed graph form a partition into subgraphs that are themselves strongly connected.
Single node is always a SCC.
* Tarjan's algorithm is a linear time algorithm to find the strongly connected components of a
directed graph, which, from here onwards will be referred as SCC.
* A graph is said to be strongly connected if every vertex is reachable from every other vertex.
The SCCs of a directed graph form a partition into subgraphs that are themselves strongly
connected. Single node is always a SCC.
* Example:
0 --------> 1 -------> 3 --------> 4
@ -38,24 +38,25 @@ import java.util.Stack;
1, 2, 0
3
4
We can also see that order of the nodes in an SCC doesn't matter since they are in cycle.
{@summary}
Tarjan's Algorithm:
* DFS search produces a DFS tree
* Strongly Connected Components form subtrees of the DFS tree.
* If we can find the head of these subtrees, we can get all the nodes in that subtree (including the head)
and that will be one SCC.
* There is no back edge from one SCC to another (here can be cross edges, but they will not be used).
Tarjan's Algorithm:
* DFS search produces a DFS tree
* Strongly Connected Components form subtrees of the DFS tree.
* If we can find the head of these subtrees, we can get all the nodes in that subtree (including
the head) and that will be one SCC.
* There is no back edge from one SCC to another (here can be cross edges, but they will not be
used).
* Kosaraju Algorithm aims at doing the same but uses two DFS traversalse whereas Tarjans algorithm does
the same in a single DFS, which leads to much lower constant factors in the latter.
* Kosaraju Algorithm aims at doing the same but uses two DFS traversalse whereas Tarjans
algorithm does the same in a single DFS, which leads to much lower constant factors in the latter.
*/
public class TarjansAlgorithm {
//Timer for tracking lowtime and insertion time
// Timer for tracking lowtime and insertion time
private int Time;
private List<List<Integer>> SCClist = new ArrayList<List<Integer>>();
@ -66,15 +67,15 @@ public class TarjansAlgorithm {
// insertionTime:Time when a node is visited 1st time while DFS traversal
// lowTime: indicates the earliest visited vertex (the vertex with minimum insertion time) that can
// be reached from a subtree rooted with a particular node.
// lowTime: indicates the earliest visited vertex (the vertex with minimum insertion time)
// that can be reached from a subtree rooted with a particular node.
int[] lowTime = new int[V];
int[] insertionTime = new int[V];
for (int i = 0; i < V; i++) {
insertionTime[i] = -1;
lowTime[i] = -1;
}
// To check if element is present in stack
boolean[] isInStack = new boolean[V];
@ -90,36 +91,36 @@ public class TarjansAlgorithm {
}
private void stronglyConnCompsUtil(int u, int[] lowTime, int[] insertionTime,
boolean[] isInStack, Stack<Integer> st, List<List<Integer>> graph) {
boolean[] isInStack, Stack<Integer> st, List<List<Integer>> graph) {
// Initialize insertion time and lowTime value of current node
insertionTime[u] = Time;
lowTime[u] = Time;
Time += 1;
//Push current node into stack
// Push current node into stack
isInStack[u] = true;
st.push(u);
// Go through all vertices adjacent to this
for (Integer vertex : graph.get(u)) {
//If the adjacent node is unvisited, do DFS
// If the adjacent node is unvisited, do DFS
if (insertionTime[vertex] == -1) {
stronglyConnCompsUtil(vertex, lowTime, insertionTime, isInStack, st, graph);
//update lowTime for the current node comparing lowtime of adj node
// update lowTime for the current node comparing lowtime of adj node
lowTime[u] = Math.min(lowTime[u], lowTime[vertex]);
} else if (isInStack[vertex]) {
//If adj node is in stack, update low
// If adj node is in stack, update low
lowTime[u] = Math.min(lowTime[u], insertionTime[vertex]);
}
}
//If lowtime and insertion time are same, current node is the head of an SCC
// head node found, get all the nodes in this SCC
// If lowtime and insertion time are same, current node is the head of an SCC
// head node found, get all the nodes in this SCC
if (lowTime[u] == insertionTime[u]) {
int w = -1;
var scc = new ArrayList<Integer>();
//Stack has all the nodes of the current SCC
// Stack has all the nodes of the current SCC
while (w != u) {
w = st.pop();
scc.add(w);
@ -128,5 +129,4 @@ public class TarjansAlgorithm {
SCClist.add(scc);
}
}
}