1
1
package com .thealgorithms .datastructures .graphs ;
2
2
3
- // Problem -> Connect all the edges with the minimum cost.
4
- // Possible Solution -> Kruskal Algorithm (KA), KA finds the minimum-spanning-tree, which means, the
5
- // group of edges with the minimum sum of their weights that connect the whole graph.
6
- // The graph needs to be connected, because if there are nodes impossible to reach, there are no
7
- // edges that could connect every node in the graph.
8
- // KA is a Greedy Algorithm, because edges are analysed based on their weights, that is why a
9
- // Priority Queue is used, to take first those less weighted.
10
- // This implementations below has some changes compared to conventional ones, but they are explained
11
- // all along the code.
12
3
import java .util .Comparator ;
13
4
import java .util .HashSet ;
14
5
import java .util .PriorityQueue ;
15
6
7
+ /**
8
+ * The Kruskal class implements Kruskal's Algorithm to find the Minimum Spanning Tree (MST)
9
+ * of a connected, undirected graph. The algorithm constructs the MST by selecting edges
10
+ * with the least weight, ensuring no cycles are formed, and using union-find to track the
11
+ * connected components.
12
+ *
13
+ * <p><strong>Key Features:</strong></p>
14
+ * <ul>
15
+ * <li>The graph is represented using an adjacency list, where each node points to a set of edges.</li>
16
+ * <li>Each edge is processed in ascending order of weight using a priority queue.</li>
17
+ * <li>The algorithm stops when all nodes are connected or no more edges are available.</li>
18
+ * </ul>
19
+ *
20
+ * <p><strong>Time Complexity:</strong> O(E log V), where E is the number of edges and V is the number of vertices.</p>
21
+ */
16
22
public class Kruskal {
17
23
18
- // Complexity: O(E log V) time, where E is the number of edges in the graph and V is the number
19
- // of vertices
20
- private static class Edge {
24
+ /**
25
+ * Represents an edge in the graph with a source, destination, and weight.
26
+ */
27
+ static class Edge {
21
28
22
- private int from ;
23
- private int to ;
24
- private int weight ;
29
+ int from ;
30
+ int to ;
31
+ int weight ;
25
32
26
33
Edge (int from , int to , int weight ) {
27
34
this .from = from ;
@@ -30,51 +37,30 @@ private static class Edge {
30
37
}
31
38
}
32
39
33
- private static void addEdge (HashSet <Edge >[] graph , int from , int to , int weight ) {
40
+ /**
41
+ * Adds an edge to the graph.
42
+ *
43
+ * @param graph the adjacency list representing the graph
44
+ * @param from the source vertex of the edge
45
+ * @param to the destination vertex of the edge
46
+ * @param weight the weight of the edge
47
+ */
48
+ static void addEdge (HashSet <Edge >[] graph , int from , int to , int weight ) {
34
49
graph [from ].add (new Edge (from , to , weight ));
35
50
}
36
51
37
- public static void main (String [] args ) {
38
- HashSet <Edge >[] graph = new HashSet [7 ];
39
- for (int i = 0 ; i < graph .length ; i ++) {
40
- graph [i ] = new HashSet <>();
41
- }
42
- addEdge (graph , 0 , 1 , 2 );
43
- addEdge (graph , 0 , 2 , 3 );
44
- addEdge (graph , 0 , 3 , 3 );
45
- addEdge (graph , 1 , 2 , 4 );
46
- addEdge (graph , 2 , 3 , 5 );
47
- addEdge (graph , 1 , 4 , 3 );
48
- addEdge (graph , 2 , 4 , 1 );
49
- addEdge (graph , 3 , 5 , 7 );
50
- addEdge (graph , 4 , 5 , 8 );
51
- addEdge (graph , 5 , 6 , 9 );
52
-
53
- System .out .println ("Initial Graph: " );
54
- for (int i = 0 ; i < graph .length ; i ++) {
55
- for (Edge edge : graph [i ]) {
56
- System .out .println (i + " <-- weight " + edge .weight + " --> " + edge .to );
57
- }
58
- }
59
-
60
- Kruskal k = new Kruskal ();
61
- HashSet <Edge >[] solGraph = k .kruskal (graph );
62
-
63
- System .out .println ("\n Minimal Graph: " );
64
- for (int i = 0 ; i < solGraph .length ; i ++) {
65
- for (Edge edge : solGraph [i ]) {
66
- System .out .println (i + " <-- weight " + edge .weight + " --> " + edge .to );
67
- }
68
- }
69
- }
70
-
52
+ /**
53
+ * Kruskal's algorithm to find the Minimum Spanning Tree (MST) of a graph.
54
+ *
55
+ * @param graph the adjacency list representing the input graph
56
+ * @return the adjacency list representing the MST
57
+ */
71
58
public HashSet <Edge >[] kruskal (HashSet <Edge >[] graph ) {
72
59
int nodes = graph .length ;
73
- int [] captain = new int [nodes ];
74
- // captain of i, stores the set with all the connected nodes to i
60
+ int [] captain = new int [nodes ]; // Stores the "leader" of each node's connected component
75
61
HashSet <Integer >[] connectedGroups = new HashSet [nodes ];
76
62
HashSet <Edge >[] minGraph = new HashSet [nodes ];
77
- PriorityQueue <Edge > edges = new PriorityQueue <>(( Comparator .comparingInt (edge -> edge .weight ) ));
63
+ PriorityQueue <Edge > edges = new PriorityQueue <>(Comparator .comparingInt (edge -> edge .weight ));
78
64
for (int i = 0 ; i < nodes ; i ++) {
79
65
minGraph [i ] = new HashSet <>();
80
66
connectedGroups [i ] = new HashSet <>();
@@ -83,18 +69,21 @@ public HashSet<Edge>[] kruskal(HashSet<Edge>[] graph) {
83
69
edges .addAll (graph [i ]);
84
70
}
85
71
int connectedElements = 0 ;
86
- // as soon as two sets merge all the elements, the algorithm must stop
87
72
while (connectedElements != nodes && !edges .isEmpty ()) {
88
73
Edge edge = edges .poll ();
89
- // This if avoids cycles
74
+
75
+ // Avoid forming cycles by checking if the nodes belong to different connected components
90
76
if (!connectedGroups [captain [edge .from ]].contains (edge .to ) && !connectedGroups [captain [edge .to ]].contains (edge .from )) {
91
- // merge sets of the captains of each point connected by the edge
77
+ // Merge the two sets of nodes connected by the edge
92
78
connectedGroups [captain [edge .from ]].addAll (connectedGroups [captain [edge .to ]]);
93
- // update captains of the elements merged
79
+
80
+ // Update the captain for each merged node
94
81
connectedGroups [captain [edge .from ]].forEach (i -> captain [i ] = captain [edge .from ]);
95
- // add Edge to minimal graph
82
+
83
+ // Add the edge to the resulting MST graph
96
84
addEdge (minGraph , edge .from , edge .to , edge .weight );
97
- // count how many elements have been merged
85
+
86
+ // Update the count of connected nodes
98
87
connectedElements = connectedGroups [captain [edge .from ]].size ();
99
88
}
100
89
}
0 commit comments