Kruskal’s Minimum Spanning Tree (MST) Algorithm

Spread the love

A minimum spanning tree (MST), sometimes know as least weight spanning tree, for a weighted, linked, undirected graph a spanning tree with a weight less than or equal to that of every other spanning tree. See this page to get more about Minimum Spanning Tree.

Kruskal’s Algorithm:

We shall now go over Kruskal’s method to determine the MST of a given weighted graph.

Sort all of the supplied graph’s edges in Kruskal’s method in rising sequence. If the newly added edge does not create a cycle, it then goes on adding fresh edges and nodes in the MST. It selects the largest weighted edge last and the smallest weighted edge first. In every phase, then, we can claim that it makes a locally optimal decision to discover the best answer. This then is a greedy algorithm.

Kruskal’s method for finding MST:


The following describes how to find MST applying Kruskal’s method:

Sort the weight of every edge in non-decreasing sequence.
Choose the weakest edge. Verify whether it creates a cycle using the currently created spanning tree. Add this edge if the cycle isn’t created. Rather, throw it away.
Till the spanning tree has (V-1) edges, repeat step #2.

The greedy method is used in Kruskal’s method of minimal cost spanning tree finding. Choosing the smallest weight edge that does not create a cycle in the MST built thus far is the greedy choice. Allow us to clarify it using a case study:

Illustration:

The graph boasts fourteen edges and nine vertices. The lowest spanning tree so produced will have (9 – 1) = 8 edges.
following sorting:


Weight
SourceDestination
176
282
265
401
425
686
723
778
807
812
934
1054
1117
1435

Below is the implementation of the above approach:

C++

// C++ program for the above approach 

#include <bits/stdc++.h> 
using namespace std; 

// DSU data structure 
// path compression + rank by union 
class DSU { 
	int* parent; 
	int* rank; 

public: 
	DSU(int n) 
	{ 
		parent = new int[n]; 
		rank = new int[n]; 

		for (int i = 0; i < n; i++) { 
			parent[i] = -1; 
			rank[i] = 1; 
		} 
	} 

	// Find function 
	int find(int i) 
	{ 
		if (parent[i] == -1) 
			return i; 

		return parent[i] = find(parent[i]); 
	} 

	// Union function 
	void unite(int x, int y) 
	{ 
		int s1 = find(x); 
		int s2 = find(y); 

		if (s1 != s2) { 
			if (rank[s1] < rank[s2]) { 
				parent[s1] = s2; 
			} 
			else if (rank[s1] > rank[s2]) { 
				parent[s2] = s1; 
			} 
			else { 
				parent[s2] = s1; 
				rank[s1] += 1; 
			} 
		} 
	} 
}; 

class Graph { 
	vector<vector<int> > edgelist; 
	int V; 

public: 
	Graph(int V) { this->V = V; } 

	// Function to add edge in a graph 
	void addEdge(int x, int y, int w) 
	{ 
		edgelist.push_back({ w, x, y }); 
	} 

	void kruskals_mst() 
	{ 
		// Sort all edges 
		sort(edgelist.begin(), edgelist.end()); 

		// Initialize the DSU 
		DSU s(V); 
		int ans = 0; 
		cout << "Following are the edges in the "
				"constructed MST"
			<< endl; 
		for (auto edge : edgelist) { 
			int w = edge[0]; 
			int x = edge[1]; 
			int y = edge[2]; 

			// Take this edge in MST if it does 
			// not forms a cycle 
			if (s.find(x) != s.find(y)) { 
				s.unite(x, y); 
				ans += w; 
				cout << x << " -- " << y << " == " << w 
					<< endl; 
			} 
		} 
		cout << "Minimum Cost Spanning Tree: " << ans; 
	} 
}; 

// Driver code 
int main() 
{ 
	Graph g(4); 
	g.addEdge(0, 1, 10); 
	g.addEdge(1, 3, 15); 
	g.addEdge(2, 3, 4); 
	g.addEdge(2, 0, 6); 
	g.addEdge(0, 3, 5); 

	// Function call 
	g.kruskals_mst(); 

	return 0; 
}

C

// C code to implement Kruskal's algorithm 

#include <stdio.h> 
#include <stdlib.h> 

// Comparator function to use in sorting 
int comparator(const void* p1, const void* p2) 
{ 
	const int(*x)[3] = p1; 
	const int(*y)[3] = p2; 

	return (*x)[2] - (*y)[2]; 
} 

// Initialization of parent[] and rank[] arrays 
void makeSet(int parent[], int rank[], int n) 
{ 
	for (int i = 0; i < n; i++) { 
		parent[i] = i; 
		rank[i] = 0; 
	} 
} 

// Function to find the parent of a node 
int findParent(int parent[], int component) 
{ 
	if (parent[component] == component) 
		return component; 

	return parent[component] 
		= findParent(parent, parent[component]); 
} 

// Function to unite two sets 
void unionSet(int u, int v, int parent[], int rank[], int n) 
{ 
	// Finding the parents 
	u = findParent(parent, u); 
	v = findParent(parent, v); 

	if (rank[u] < rank[v]) { 
		parent[u] = v; 
	} 
	else if (rank[u] > rank[v]) { 
		parent[v] = u; 
	} 
	else { 
		parent[v] = u; 

		// Since the rank increases if 
		// the ranks of two sets are same 
		rank[u]++; 
	} 
} 

// Function to find the MST 
void kruskalAlgo(int n, int edge[n][3]) 
{ 
	// First we sort the edge array in ascending order 
	// so that we can access minimum distances/cost 
	qsort(edge, n, sizeof(edge[0]), comparator); 

	int parent[n]; 
	int rank[n]; 

	// Function to initialize parent[] and rank[] 
	makeSet(parent, rank, n); 

	// To store the minimun cost 
	int minCost = 0; 

	printf( 
		"Following are the edges in the constructed MST\n"); 
	for (int i = 0; i < n; i++) { 
		int v1 = findParent(parent, edge[i][0]); 
		int v2 = findParent(parent, edge[i][1]); 
		int wt = edge[i][2]; 

		// If the parents are different that 
		// means they are in different sets so 
		// union them 
		if (v1 != v2) { 
			unionSet(v1, v2, parent, rank, n); 
			minCost += wt; 
			printf("%d -- %d == %d\n", edge[i][0], 
				edge[i][1], wt); 
		} 
	} 

	printf("Minimum Cost Spanning Tree: %d\n", minCost); 
} 

// Driver code 
int main() 
{ 
	int edge[5][3] = { { 0, 1, 10 }, 
					{ 0, 2, 6 }, 
					{ 0, 3, 5 }, 
					{ 1, 3, 15 }, 
					{ 2, 3, 4 } }; 

	kruskalAlgo(5, edge); 

	return 0; 
}

Python3

# Python program for Kruskal's algorithm to find 
# Minimum Spanning Tree of a given connected, 
# undirected and weighted graph 


# Class to represent a graph 
class Graph: 

	def __init__(self, vertices): 
		self.V = vertices 
		self.graph = [] 

	# Function to add an edge to graph 
	def addEdge(self, u, v, w): 
		self.graph.append([u, v, w]) 

	# A utility function to find set of an element i 
	# (truly uses path compression technique) 
	def find(self, parent, i): 
		if parent[i] != i: 

			# Reassignment of node's parent 
			# to root node as 
			# path compression requires 
			parent[i] = self.find(parent, parent[i]) 
		return parent[i] 

	# A function that does union of two sets of x and y 
	# (uses union by rank) 
	def union(self, parent, rank, x, y): 

		# Attach smaller rank tree under root of 
		# high rank tree (Union by Rank) 
		if rank[x] < rank[y]: 
			parent[x] = y 
		elif rank[x] > rank[y]: 
			parent[y] = x 

		# If ranks are same, then make one as root 
		# and increment its rank by one 
		else: 
			parent[y] = x 
			rank[x] += 1

	# The main function to construct MST 
	# using Kruskal's algorithm 
	def KruskalMST(self): 

		# This will store the resultant MST 
		result = [] 

		# An index variable, used for sorted edges 
		i = 0

		# An index variable, used for result[] 
		e = 0

		# Sort all the edges in 
		# non-decreasing order of their 
		# weight 
		self.graph = sorted(self.graph, 
							key=lambda item: item[2]) 

		parent = [] 
		rank = [] 

		# Create V subsets with single elements 
		for node in range(self.V): 
			parent.append(node) 
			rank.append(0) 

		# Number of edges to be taken is less than to V-1 
		while e < self.V - 1: 

			# Pick the smallest edge and increment 
			# the index for next iteration 
			u, v, w = self.graph[i] 
			i = i + 1
			x = self.find(parent, u) 
			y = self.find(parent, v) 

			# If including this edge doesn't 
			# cause cycle, then include it in result 
			# and increment the index of result 
			# for next edge 
			if x != y: 
				e = e + 1
				result.append([u, v, w]) 
				self.union(parent, rank, x, y) 
			# Else discard the edge 

		minimumCost = 0
		print("Edges in the constructed MST") 
		for u, v, weight in result: 
			minimumCost += weight 
			print("%d -- %d == %d" % (u, v, weight)) 
		print("Minimum Spanning Tree", minimumCost) 


# Driver code 
if __name__ == '__main__': 
	g = Graph(4) 
	g.addEdge(0, 1, 10) 
	g.addEdge(0, 2, 6) 
	g.addEdge(0, 3, 5) 
	g.addEdge(1, 3, 15) 
	g.addEdge(2, 3, 4) 

	# Function call 
	g.KruskalMST() 


Java

// Java program for Kruskal's algorithm 

import java.util.ArrayList; 
import java.util.Comparator; 
import java.util.List; 

public class KruskalsMST { 

	// Defines edge structure 
	static class Edge { 
		int src, dest, weight; 

		public Edge(int src, int dest, int weight) 
		{ 
			this.src = src; 
			this.dest = dest; 
			this.weight = weight; 
		} 
	} 

	// Defines subset element structure 
	static class Subset { 
		int parent, rank; 

		public Subset(int parent, int rank) 
		{ 
			this.parent = parent; 
			this.rank = rank; 
		} 
	} 

	// Starting point of program execution 
	public static void main(String[] args) 
	{ 
		int V = 4; 
		List<Edge> graphEdges = new ArrayList<Edge>( 
			List.of(new Edge(0, 1, 10), new Edge(0, 2, 6), 
					new Edge(0, 3, 5), new Edge(1, 3, 15), 
					new Edge(2, 3, 4))); 

		// Sort the edges in non-decreasing order 
		// (increasing with repetition allowed) 
		graphEdges.sort(new Comparator<Edge>() { 
			@Override public int compare(Edge o1, Edge o2) 
			{ 
				return o1.weight - o2.weight; 
			} 
		}); 

		kruskals(V, graphEdges); 
	} 

	// Function to find the MST 
	private static void kruskals(int V, List<Edge> edges) 
	{ 
		int j = 0; 
		int noOfEdges = 0; 

		// Allocate memory for creating V subsets 
		Subset subsets[] = new Subset[V]; 

		// Allocate memory for results 
		Edge results[] = new Edge[V]; 

		// Create V subsets with single elements 
		for (int i = 0; i < V; i++) { 
			subsets[i] = new Subset(i, 0); 
		} 

		// Number of edges to be taken is equal to V-1 
		while (noOfEdges < V - 1) { 

			// Pick the smallest edge. And increment 
			// the index for next iteration 
			Edge nextEdge = edges.get(j); 
			int x = findRoot(subsets, nextEdge.src); 
			int y = findRoot(subsets, nextEdge.dest); 

			// If including this edge doesn't cause cycle, 
			// include it in result and increment the index 
			// of result for next edge 
			if (x != y) { 
				results[noOfEdges] = nextEdge; 
				union(subsets, x, y); 
				noOfEdges++; 
			} 

			j++; 
		} 

		// Print the contents of result[] to display the 
		// built MST 
		System.out.println( 
			"Following are the edges of the constructed MST:"); 
		int minCost = 0; 
		for (int i = 0; i < noOfEdges; i++) { 
			System.out.println(results[i].src + " -- "
							+ results[i].dest + " == "
							+ results[i].weight); 
			minCost += results[i].weight; 
		} 
		System.out.println("Total cost of MST: " + minCost); 
	} 

	// Function to unite two disjoint sets 
	private static void union(Subset[] subsets, int x, 
							int y) 
	{ 
		int rootX = findRoot(subsets, x); 
		int rootY = findRoot(subsets, y); 

		if (subsets[rootY].rank < subsets[rootX].rank) { 
			subsets[rootY].parent = rootX; 
		} 
		else if (subsets[rootX].rank 
				< subsets[rootY].rank) { 
			subsets[rootX].parent = rootY; 
		} 
		else { 
			subsets[rootY].parent = rootX; 
			subsets[rootX].rank++; 
		} 
	} 

	// Function to find parent of a set 
	private static int findRoot(Subset[] subsets, int i) 
	{ 
		if (subsets[i].parent == i) 
			return subsets[i].parent; 

		subsets[i].parent 
			= findRoot(subsets, subsets[i].parent); 
		return subsets[i].parent; 
	} 
} 

Output

Following are the edges in the constructed MST
2 -- 3 == 4
0 -- 3 == 5
0 -- 1 == 10
Minimum Cost Spanning Tree: 19

Time complexity is O(E * logE) or O(E * logV).

  • Edge sorting demands O(E * logE) time.
  • We iterate over all edges and use the find-union technique following sorting. At most O(logV), the find and union processes can take.
  • Overall complexity then is O(E * logE + E * logV) time.
  • O(logV) and O(logE) are the same as E’s value can be at most O(V2). The general temporal complexity is thus O(E * logE) or O(E*logV).
  • O(V + E), where V is the graph’s verticle count and E is its edge count.