Kruskal's Algorithm
Algorithm · Stretch
Step through it: Union-Find pattern
Step 1 of 6
Goal: keep track of which items belong to the same group, and merge groups quickly. Start with 5 separate groups. Each item points to a parent; an item that points to itself is the leader of its group.
Step 2 of 6
Join 0 and 1: make 0 the leader of 1.
Step 3 of 6
Join 2 and 3: make 2 the leader of 3.
Step 4 of 6
Join 1 and 3: follow the parents to find each leader. 1 leads to 0, and 3 leads to 2. Different leaders, so hang leader 0 under 2.
Step 5 of 6
Are 0 and 3 in the same group? Follow parents from each: both end at 2. Yes. Shortcuts that point items straight at their leader (path compression) keep these walks very short. This is union-find.
Step 6 of 6
Your turn.
Kruskal's algorithm is a minimum-spanning-tree algorithm which finds an edge of the least possible weight that connects any two trees in the forest. It is a greedy algorithm in graph theory as it finds a minimum spanning tree for a connected weighted graph adding increasing cost arcs at each step. This means it finds a subset of the edges that forms a tree that includes every vertex, where the total weight of all the edges in the tree is minimized. If the graph is not connected, then it finds a minimum spanning forest (a minimum spanning tree for each connected component).
A demo for Kruskal's algorithm based on Euclidean distance.
Minimum Spanning Tree
A minimum spanning tree (MST) or minimum weight spanning tree is a subset of the edges of a connected, edge-weighted (un)directed graph that connects all the vertices together, without any cycles and with the minimum possible total edge weight. That is, it is a spanning tree whose sum of edge weights is as small as possible. More generally, any edge-weighted undirected graph (not necessarily connected) has a minimum spanning forest, which is a union of the minimum spanning trees for its connected components.
A planar graph and its minimum spanning tree. Each edge is labeled with its weight, which here is roughly proportional to its length.
This figure shows there may be more than one minimum spanning tree in a graph. In the figure, the two trees below the graph are two possibilities of minimum spanning tree of the given graph.
Code
import Graph from '../../../data-structures/graph/Graph';
import QuickSort from '../../sorting/quick-sort/QuickSort';
import DisjointSet from '../../../data-structures/disjoint-set/DisjointSet';
/**
* @param {Graph} graph
* @return {Graph}
*/
export default function kruskal(graph) {
// It should fire error if graph is directed since the algorithm works only
// for undirected graphs.
if (graph.isDirected) {
throw new Error('Kruskal\'s algorithms works only for undirected graphs');
}
// Init new graph that will contain minimum spanning tree of original graph.
const minimumSpanningTree = new Graph();
// Sort all graph edges in increasing order.
const sortingCallbacks = {
/**
* @param {GraphEdge} graphEdgeA
* @param {GraphEdge} graphEdgeB
*/
compareCallback: (graphEdgeA, graphEdgeB) => {
if (graphEdgeA.weight === graphEdgeB.weight) {
return 1;
}
return graphEdgeA.weight <= graphEdgeB.weight ? -1 : 1;
},
};
const sortedEdges = new QuickSort(sortingCallbacks).sort(graph.getAllEdges());
// Create disjoint sets for all graph vertices.
const keyCallback = (graphVertex) => graphVertex.getKey();
const disjointSet = new DisjointSet(keyCallback);
graph.getAllVertices().forEach((graphVertex) => {
disjointSet.makeSet(graphVertex);
});
// Go through all edges started from the minimum one and try to add them
// to minimum spanning tree. The criteria of adding the edge would be whether
// it is forms the cycle or not (if it connects two vertices from one disjoint
// set or not).
for (let edgeIndex = 0; edgeIndex < sortedEdges.length; edgeIndex += 1) {
/** @var {GraphEdge} currentEdge */
const currentEdge = sortedEdges[edgeIndex];
// Check if edge forms the cycle. If it does then skip it.
if (!disjointSet.inSameSet(currentEdge.startVertex, currentEdge.endVertex)) {
// Unite two subsets into one.
disjointSet.union(currentEdge.startVertex, currentEdge.endVertex);
// Add this edge to spanning tree.
minimumSpanningTree.addEdge(currentEdge);
}
}
return minimumSpanningTree;
}References
Practice
Union-Find
- Find if Path Exists in GraphEasy
- Number of ProvincesMedium
- Redundant ConnectionMedium
- Accounts MergeMedium
- Graph Valid TreeMedium
- Number of Connected Components in an Undirected GraphMedium
- Satisfiability of Equality EquationsMedium
- Most Stones Removed with Same Row or ColumnMedium
- Evaluate DivisionMedium
- Number of Islands IIHard
- Min Cost to Connect All PointsHard
- Swim in Rising WaterHard
Greedy
- Assign CookiesEasy
- Lemonade ChangeEasy
- Best Time to Buy and Sell Stock IIEasy
- Can Place FlowersEasy
- Jump GameMedium
- Jump Game IIMedium
- Gas StationMedium
- Hand of StraightsMedium
- Task SchedulerMedium
- Queue Reconstruction by HeightMedium
- Partition LabelsMedium
- Maximum SubarrayMedium
- CandyHard
- Minimum Number of Taps to Open to Water a GardenHard
Spotted a mistake or something unclear? Report it on GitHub.