Kruskal

Utilized in the discovery of the minimum spanning tree, this method involves arranging the edges in descending order and sequentially incorporating the smallest unused edge. This process aims to construct a tree encompassing all nodes while adhering to these criteria. Here’s an example implementation of Kruskal’s algorithm:

Python

# Define a helper function to find the parent of a node in a set
def find(parent, i):
    if parent[i] == i:
        return i
    return find(parent, parent[i])

# Define the main function that implements Kruskal's algorithm
def kruskal(graph):
    # Sort the edges by weight in non-decreasing order
    edges = sorted(graph, key=lambda x: x[2])

    # Initialize an empty set of parent nodes
    parent = dict()

    # Create a parent node for each vertex
    for edge in edges:
        parent[edge[0]] = edge[0]
        parent[edge[1]] = edge[1]

    # Initialize an empty list to store the minimum spanning tree
    mst = []

    # Iterate over the edges in the sorted order
    for edge in edges:
        # Find the parent of each node in the edge
        p1 = find(parent, edge[0])
        p2 = find(parent, edge[1])

        # If the parent nodes are different, add the edge to the minimum spanning tree
        if p1 != p2:
            mst.append(edge)

            # Union the sets of nodes by setting one node's parent to the other node's parent
            parent[p1] = p2

    return mst

This implementation assumes that the graph is represented as a list of tuples, where each tuple represents an edge with the format (node1, node2, weight). The kruskal function takes this list as input, and returns a list of tuples representing the edges in the minimum spanning tree.

C


#include <stdlib.h>

// Define a helper function to find the parent of a node in a set
int find(int parent[], int i) {
    if (parent[i] == i)
        return i;
    return find(parent, parent[i]);
}

// Define the main function that implements Kruskal's algorithm
int** kruskal(int** graph, int numEdges) {
    // Sort the edges by weight in non-decreasing order
    for (int i = 0; i < numEdges - 1; i++) {
        for (int j = 0; j < numEdges - i - 1; j++) {
            if (graph[j][2] > graph[j + 1][2]) {
                int* temp = graph[j];
                graph[j] = graph[j + 1];
                graph[j + 1] = temp;
            }
        }
    }

    // Initialize an empty array of parent nodes
    int* parent = (int*)malloc(numEdges * sizeof(int));

    // Create a parent node for each vertex
    for (int i = 0; i < numEdges; i++) {
        parent[graph[i][0]] = graph[i][0];
        parent[graph[i][1]] = graph[i][1];
    }

    // Initialize an empty array to store the minimum spanning tree
    int** mst = (int**)malloc(numEdges * sizeof(int*));
    int mstSize = 0;

    // Iterate over the edges in the sorted order
    for (int i = 0; i < numEdges; i++) {
        int* edge = graph[i];

        // Find the parent of each node in the edge
        int p1 = find(parent, edge[0]);
        int p2 = find(parent, edge[1]);

        // If the parent nodes are different, add the edge to the minimum spanning tree
        if (p1 != p2) {
            mst[mstSize] = edge;
            mstSize++;

            // Union the sets of nodes by setting one node's parent to the other node's parent
            parent[p1] = p2;
        }
    }

    // Resize the mst array to its actual size
    mst = (int**)realloc(mst, mstSize * sizeof(int*));

    // Free the parent array
    free(parent);

    return mst;
}

Rust

fn find(parent: &mut Vec<usize>, i: usize) -> usize {
    if parent[i] == i {
        return i;
    }
    parent[i] = find(parent, parent[i]);
    parent[i]
}

fn kruskal(graph: &Vec<(usize, usize, i32)>) -> Vec<(usize, usize, i32)> {
    // Sort the edges by weight in non-decreasing order
    let mut edges = graph.clone();
    edges.sort_by_key(|x| x.2);

    // Initialize an empty set of parent nodes
    let mut parent: Vec<usize> = Vec::new();

    // Create a parent node for each vertex
    for edge in &edges {
        parent.resize_with(edge.0.max(edge.1) + 1, || parent.len());
        parent[edge.0] = edge.0;
        parent[edge.1] = edge.1;
    }

    // Initialize an empty vector to store the minimum spanning tree
    let mut mst = Vec::new();

    // Iterate over the edges in the sorted order
    for edge in &edges {
        // Find the parent of each node in the edge
        let p1 = find(&mut parent, edge.0);
        let p2 = find(&mut parent, edge.1);

        // If the parent nodes are different, add the edge to the minimum spanning tree
        if p1 != p2 {
            mst.push(*edge);

            // Union the sets of nodes by setting one node's parent to the other node's parent
            parent[p1] = p2;
        }
    }

    mst
}

Explanation:

  • fn find(parent: &mut Vec, i: usize) -> usize is a helper function that finds the parent of a node in a set. It takes a mutable reference to a vector parent that contains the parent nodes for each vertex, and an index i for the node whose parent to find. It returns the parent node index for i.
  • fn kruskal(graph: &Vec<(usize, usize, i32)>) -> Vec<(usize, usize, i32)> is the main function that implements Kruskal’s algorithm. It takes a reference to a vector of tuples graph that represent the edges of a weighted undirected graph. Each tuple contains the indices of the two vertices that the edge connects, and the weight of the edge. It returns a vector of tuples that represent the edges of the minimum spanning tree.
  • let mut edges = graph.clone(); edges.sort_by_key(|x| x.2); creates a mutable copy of the input graph and sorts the edges by their weights in non-decreasing order.
  • let mut parent: Vec = Vec::new(); initializes an empty vector to store the parent nodes for each vertex.
  • parent.resize_with(edge.0.max(edge.1) + 1, || parent.len()); resizes parent to accommodate the indices of the vertices in the edges. It ensures that the size of parent is at least the maximum vertex index plus one. It uses || parent.len() as a closure to initialize new elements of parent to the current length of parent.
  • parent[edge.0] = edge.0; parent[edge.1] = edge.1; initializes the parent nodes for the vertices in each edge.
  • let mut mst = Vec::new(); initializes an empty vector to store the edges of the minimum spanning tree.
  • for edge in &edges { … } iterates
Click to view another code.

Python

class Graph:
    def __init__(self, vertices):
        self.V = vertices
        self.graph = []
 
    def add_edge(self, u, v, w):
        self.graph.append([u, v, w])
 
    # Search function
    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])


def apply_union(self, parent, rank, x, y):
        xroot = self.find(parent, x)
        yroot = self.find(parent, y)
        if rank[xroot] < rank[yroot]:
            parent[xroot] = yroot
        elif rank[xroot] > rank[yroot]:
            parent[yroot] = xroot
        else:
            parent[yroot] = xroot
            rank[xroot] += 1
 
    # Applying Kruskal’s algorithm
    def kruskal_algo(self):
        result = []
        i, e = 0, 0
        self.graph = sorted(self.graph, key=lambda item: item[2])
        parent = []
        rank = []
        for node in range(self.V):
            parent.append(node)
            rank.append(0)
        while e < self.V - 1:
            u, v, w = self.graph[i]
            i = i + 1
            x = self.find(parent, u)
            y = self.find(parent, v)
            if x != y:
                e = e + 1
                result.append([u, v, w])
                self.apply_union(parent, rank, x, y)
        for u, v, weight in result:
            print("%d - %d: %d" % (u, v, weight))


g = Graph(6)
g.add_edge(0, 1, 4)
g.add_edge(0, 2, 4)
g.add_edge(1, 2, 2)
g.add_edge(1, 0, 4)
g.add_edge(2, 0, 4)
g.add_edge(2, 1, 2)
g.add_edge(2, 3, 3)
g.add_edge(2, 5, 2)
g.add_edge(2, 4, 4)
g.add_edge(3, 2, 3)
g.add_edge(3, 4, 3)
g.add_edge(4, 2, 4)
g.add_edge(4, 3, 3)
g.add_edge(5, 2, 2)
g.add_edge(5, 4, 3)
g.kruskal_algo()

Previous
Next