Skip to content

Instantly share code, notes, and snippets.

@jianminchen
Created April 14, 2017 19:59
Show Gist options
  • Save jianminchen/cdab7242d0a1d2764ebdcf59ef30e89e to your computer and use it in GitHub Desktop.
Save jianminchen/cdab7242d0a1d2764ebdcf59ef30e89e to your computer and use it in GitHub Desktop.
Minimum spanning tree - Kruskal algorithm
#if DEBUG
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endif
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace JuliaPracticeOnApril42017
{
/// <summary>
/// Study the article:
/// http://www.geeksforgeeks.org/greedy-algorithms-set-2-kruskals-minimum-spanning-tree-mst/
///
/// greedy algorithm set 2 - kurskals minimum spanning tree
/// April 14, 2017 10:00 am - 1:00 pm
/// </summary>
class Graph
{
// A class to represent a graph edge
internal class Edge
{
public int src {get; set;}
public int dest {get; set;}
public int weight {get; set;}
// Comparator function used for sorting edges based on
// their weight
public static int Compare(Edge a, Edge b)
{
return a.weight - b.weight;
}
};
// A class to represent a subset for union-find
internal class Subset
{
public int parent {get; set;}
public int rank {get; set;}
};
// V-> no. of vertices & E->no.of edges
public int noVertices, noEdges;
// collection of all edges
Edge[] edges;
// Creates a graph with V vertices and E edges
public Graph(int v, int e)
{
noVertices = v;
noEdges = e;
edges = new Edge[noEdges];
for (int i = 0; i < e; ++i)
{
edges[i] = new Edge();
}
}
/// <summary>
/// A utility function to find set of an element i
/// (uses path compression technique)
/// </summary>
/// <param name="subsets"></param>
/// <param name="i"></param>
/// <returns></returns>
int find(Subset[] subsets, int i)
{
// find root and make root as parent of i (path compression)
if (subsets[i].parent != i)
{
subsets[i].parent = find(subsets, subsets[i].parent);
}
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
public void Union(Subset[] subsets, int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high rank tree
// (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
{
subsets[xroot].parent = yroot;
}
else if (subsets[xroot].rank > subsets[yroot].rank)
{
subsets[yroot].parent = xroot;
}
// If ranks are same, then make one as root and increment
// its rank by one
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
/// <summary>
/// Construct minimum spanning tree using Kruskal's algorithm
/// </summary>
public Edge[] KruskalMST()
{
int mstEdges = noVertices - 1;
var minimumSpanTree = new Edge[mstEdges];
for (int i = 0; i < mstEdges; ++i)
{
minimumSpanTree[i] = new Edge();
}
// sort by weight
Array.Sort(edges, Edge.Compare);
// Allocate memory for creating subsets
var subsets = new Subset[noVertices];
for (int i = 0; i < noVertices; ++i)
{
subsets[i] = new Subset();
}
// Create subsets with single elements
for (int v = 0; v < noVertices; ++v)
{
subsets[v].parent = v;
subsets[v].rank = 0;
}
int edgeIndex = 0; // Index used to pick next edge
int treeIndex = 0;
// Number of edges to be taken is equal to V-1
while (treeIndex < noVertices - 1)
{
// Step 2: Pick the smallest edge. And increment the index
// for next iteration
var edge = new Edge();
edge = edges[edgeIndex++];
int rootOfSource = find(subsets, edge.src);
int rootOfDestination = find(subsets, edge.dest);
// If including this edge does't cause cycle, include it
// in result and increment the index of result for next edge
if (rootOfSource != rootOfDestination)
{
minimumSpanTree[treeIndex++] = edge;
Union(subsets, rootOfSource, rootOfDestination);
}
// Else discard the next_edge
}
return minimumSpanTree;
}
static void Main(string[] args)
{
int vertices = 4;
int edges = 5;
var graph = new Graph(vertices, edges);
// add edge 0-1
graph.edges[0].src = 0;
graph.edges[0].dest = 1;
graph.edges[0].weight = 10;
// add edge 0-2
graph.edges[1].src = 0;
graph.edges[1].dest = 2;
graph.edges[1].weight = 6;
// add edge 0-3
graph.edges[2].src = 0;
graph.edges[2].dest = 3;
graph.edges[2].weight = 5;
// add edge 1-3
graph.edges[3].src = 1;
graph.edges[3].dest = 3;
graph.edges[3].weight = 15;
// add edge 2-3
graph.edges[4].src = 2;
graph.edges[4].dest = 3;
graph.edges[4].weight = 4;
var minimumSpanningTree = graph.KruskalMST();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment