11package com .thealgorithms .datastructures .graphs ;
22
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.
123import java .util .Comparator ;
134import java .util .HashSet ;
145import java .util .PriorityQueue ;
156
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+ */
1622public class Kruskal {
1723
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 {
2128
22- private int from ;
23- private int to ;
24- private int weight ;
29+ int from ;
30+ int to ;
31+ int weight ;
2532
2633 Edge (int from , int to , int weight ) {
2734 this .from = from ;
@@ -30,51 +37,30 @@ private static class Edge {
3037 }
3138 }
3239
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 ) {
3449 graph [from ].add (new Edge (from , to , weight ));
3550 }
3651
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+ */
7158 public HashSet <Edge >[] kruskal (HashSet <Edge >[] graph ) {
7259 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
7561 HashSet <Integer >[] connectedGroups = new HashSet [nodes ];
7662 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 ));
7864 for (int i = 0 ; i < nodes ; i ++) {
7965 minGraph [i ] = new HashSet <>();
8066 connectedGroups [i ] = new HashSet <>();
@@ -83,18 +69,21 @@ public HashSet<Edge>[] kruskal(HashSet<Edge>[] graph) {
8369 edges .addAll (graph [i ]);
8470 }
8571 int connectedElements = 0 ;
86- // as soon as two sets merge all the elements, the algorithm must stop
8772 while (connectedElements != nodes && !edges .isEmpty ()) {
8873 Edge edge = edges .poll ();
89- // This if avoids cycles
74+
75+ // Avoid forming cycles by checking if the nodes belong to different connected components
9076 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
9278 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
9481 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
9684 addEdge (minGraph , edge .from , edge .to , edge .weight );
97- // count how many elements have been merged
85+
86+ // Update the count of connected nodes
9887 connectedElements = connectedGroups [captain [edge .from ]].size ();
9988 }
10089 }
0 commit comments