3 minute read

Kruskal’s algorithm is a greedy algorithm for solving the problem of finding a minimal spanning tree (MST) in a weighted and undirected graph. The goal is to find a subset of edges that will create a tree which contains all the original vertices, where the sum of the weights “Weighted graph” of all the edges in the tree is minimized.

Steps

  • create a forest $F$ (a set of trees), where each vertex in the graph is a separate tree
  • create a set $S$ containing all the edges in the graph
  • while $S$ is nonempty and $F$ is not yet spanning
    • remove an edge with minimum weight from $S$
    • if the removed edge connects two different trees then add it to the forest $F$, combining two trees into a single tree

At the termination of the algorithm, the forest forms a minimum spanning forest of the graph. If the graph is connected, the forest has a single component and forms a minimum spanning tree.

Time Complexity

Time complexity mostly affected by sorting the edges at the beginning of the algorithm. In graph $G=(V,E)$ the time complexity is $O(|E| \cdot \log |V|)$ . If the edges of $G$ are pre-sorted then the time complexity is $O(|E| \cdot \alpha (|V|))$ and $ \alpha $ is the Ackermann function which measured as $ \alpha (n)≅O(1)$ .

Algorithm Pseudocode

Kruskal(G): // O(|E|log|V|)
    create Tree T  

    for each vV(G) do: // O(|V|)
        MakeSet(v)
    end-for

    // sort E in increasing order by edges weight
    Sort(E(G)) // O(|E|log|V|)

    for each eE(G) do: // O(|E|)
        if FindSet(e.u)  FindSet(e.v) then:
            T.add(e)
            Union(e.u, e.v) //𝑶(α(V)) ≅ 𝑶(𝟏)
        end-if
        if |E(T)| = |V(G)|-1 then:
            return T
        end-if
    end-for
    
    return T
    
end-Kruskal

MakeSet(v): // O(1)
    v.parent  v
end-MakeSet

FindSet(v): //𝑶(α(V)) ≅ 𝑶(𝟏)
    if v = v.parent then:
        return v.parent
    else:
        return FindSet(v.parent)
    end-if
end-FindSet

Union(u,v): //𝑶(α(V)) ≅ 𝑶(𝟏)
    uRoot  FindSet(u)
    vRoot  FindSet(v)
    uRoot.parent  vRoot
end-Union

Return the sum of weights of all the MST

SumOfMST(G):
    sum  0
    T  Kruskal(G)

    for each eE(T) do: 
        sum  sum + e.weight
    end-for

    return sum
end-SumOfMST

Maximum Spanning Tree

MaximumSpanningTreeSum(G)

    for each eE(G) do:
        e.weight  (-1)*(e.weight)
    end-for

    T  Kruskal(G)
    sum  0

    for each eE(T) do:
        e.weight  (-1)*(e.weight)
        sum  sum + e.weight
    end-for

    return sum
end-MaximumSpanningTreeSum

Java Code Version

public  class  Kruskal {  
  
	private Edge[] graph, tree;  
	private DisjointSets group;  
	private  int node_size, tree_size;  
	  
	public  Kruskal(Edge[] g) {  
	this.graph = new Edge[g.length];  
	  
	for(int i = 0; i < g.length; i++) {  
		graph[i] = new Edge(g[i].v, g[i].u, g[i].weight);  
	}  
	node_size = 0;  
	tree_size = 0;  
	for(Edge edge : graph) {  
		if(edge.v > node_size) node_size = edge.v;  
		if(edge.u > node_size) node_size = edge.u;  
	}  
	node_size++;  
	  
	group = new DisjointSets(node_size);  
	tree = new Edge[node_size-1];  
	  
	for (int i = 0; i < node_size; i++) {  
		group.make_set(i);  
	}  
		findMTS();  
	}  
	  
	private  void  findMTS() {  
		Arrays.sort(graph); // O(|E|log|E|)  
		for(Edge edge : graph) {  
			if(tree_size < node_size-1) {  
				if(group.union(edge.v, edge.u)) {  
				tree[tree_size++] = edge;  
				}  
			}  
			else {  
			break;  
			}  
		}  
	}  
	  
	public Edge[] getTree() {  
	return  this.tree;  
	}  
	  
	/***************************************************  
	* DisjointSets CLASS! *****************************  
	*/  
	public  static  class  DisjointSets {  
		private  int[] parent, rank; //rank[k]>=height of tree number k  
		  
		public  DisjointSets(int length) {  
		parent = new  int[length];  
		rank = new  int[length];  
		}  
		public  void  make_set(int k) {  
		parent[k] = k;  
		rank[k] = 0;  
		}  
		public  boolean  union(int v, int u) {  
		int root_v = find(v);  
		int root_u = find(u);  
		  
		if(root_v == root_u) { // if its equals = there is a circle.  
		return  false;  
		}  
		else {  
		if (rank[root_u] > rank[root_v]) {  
		parent[root_v] = root_u;  
		} else  if (rank[root_v] > rank[root_u]) {  
		parent[root_u] = root_v;  
		} else {  
		parent[root_v] = root_u;  
		rank[root_u]++;  
		}  
		return  true;  
		}  
	}  
	public  int  find(int v) {  
	if(parent[v] != v) {  
	parent[v] = find(parent[v]);  
	}  
	return parent[v];  
	}  
	}  
	/***************************************************  
	* EDGE CLASS! *************************************  
	*/  
	public  static  class  Edge  implements  Comparable<Edge> {  
		int v, u, weight;  
		public  Edge(int v, int u, int weight) {  
			this.v = v;  
			this.u = u;  
			this.weight = weight;  
		}  
		@Override  
		public String toString() {  
			return  "{" +  
			"v=" + v +  
			", u=" + u +  
			", weight=" + weight +  
			'}';  
		}  
		@Override  
		public  int  compareTo(Edge o) {  
			return Integer.compare(this.weight,o.weight);  
		}  
	}  
}

Leave a comment