chore(CSharp): added kruskals algorithm (#485)

pull/488/head
Waqar Hassan Khan 2021-09-26 06:16:39 +06:00 committed by GitHub
parent 464b32a3d6
commit b561c2e0dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 194 additions and 0 deletions

View File

@ -26,3 +26,4 @@ For running the `.cs` file please using [.Net Finddle](https://dotnetfiddle.net/
## Graph
- [Depth First Search](src/Graph/depth-first-search.cs)
- [Kruskals Algorithm to Find Minimum Spanning Tree](src/Graph/kruskals-algorithm.cs)

View File

@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Algorithms.Graph
{
public class KruskalsAlgorithm
{
public class DisjointSetUnion
{
private int[] parent, rank;
public DisjointSetUnion(int totalNodes)
{
rank = Enumerable.Repeat(1, totalNodes + 1).ToArray();
parent = Enumerable.Range(0, totalNodes + 1).ToArray();
}
public void Union(int nodeA, int nodeB)
{
int parentA = Find(nodeA);
int parentB = Find(nodeB);
if(rank[parentA] > rank[parentB])
{
parent[parentB] = parentA;
rank[parentA] += rank[parentB];
}
else
{
parent[parentA] = parentB;
rank[parentB] += rank[parentA];
}
}
public int Find(int node)
{
if(parent[node] == node)
{
return node;
}
return parent[node] = Find(parent[node]);
}
}
public class Graph
{
private DisjointSetUnion _nodesTaken;
private List<Tuple<int, int, int>> edges;
public Graph(int totalNodes)
{
_nodesTaken = new DisjointSetUnion(totalNodes);
edges = new List<Tuple<int, int, int>>();
}
public void AddEdge(int source, int destination, int weight) =>
edges.Add(new Tuple<int, int, int>(source, destination, weight));
public List<Tuple<int, int, int>> GetMST()
{
edges = (from edge in edges
orderby edge.Item3
select edge).ToList();
List<Tuple<int, int, int>> results = new List<Tuple<int, int, int>>();
foreach(var edge in edges)
{
if(_nodesTaken.Find(edge.Item1) != _nodesTaken.Find(edge.Item2))
{
_nodesTaken.Union(edge.Item1, edge.Item2);
results.Add(new Tuple<int, int, int>(edge.Item1, edge.Item2, edge.Item3));
}
}
return results;
}
}
public static Object KruskalDriver(int totalNodes, List<Tuple<int, int, int>> edges)
{
Graph graph = new Graph(totalNodes);
foreach(var edge in edges)
{
graph.AddEdge(edge.Item1, edge.Item2, edge.Item3);
}
var results = graph.GetMST();
int totalWeight = 0;
foreach(var edge in results)
{
totalWeight += edge.Item3;
}
Object ret = new {
weight = totalWeight,
edges = results
};
return ret;
}
public static void Main()
{
List<Tuple<int, int, int>> edges = new List<Tuple<int, int, int>>()
{
new Tuple<int, int, int>(1, 2, 4),
new Tuple<int, int, int>(1, 8, 8),
new Tuple<int, int, int>(2, 8, 11),
new Tuple<int, int, int>(2, 3, 8),
new Tuple<int, int, int>(3, 9, 2),
new Tuple<int, int, int>(8, 9, 7),
new Tuple<int, int, int>(8, 7, 1),
new Tuple<int, int, int>(7, 9, 6),
new Tuple<int, int, int>(3, 4, 7),
new Tuple<int, int, int>(3, 6, 4),
new Tuple<int, int, int>(6, 7, 2),
new Tuple<int, int, int>(4, 6, 14),
new Tuple<int, int, int>(4, 5, 9),
new Tuple<int, int, int>(5, 6, 10)
};
var result = KruskalDriver(9, edges);
var propertyInfo = result.GetType().GetProperty("weight");
var weight = propertyInfo.GetValue(result, null);
Console.WriteLine(weight);
}
}
}

View File

@ -0,0 +1,61 @@
using System;
using NUnit.Framework;
using System.Collections.Generic;
namespace Algorithms.Tests.Graph
{
[TestFixture]
class KruskalsAlgortihm
{
static Object[] TestCasesForKruskalsAlgorithm =
{
new object[]
{
9,
new List<Tuple<int, int, int>>()
{
new Tuple<int, int, int>(1, 2, 4),
new Tuple<int, int, int>(1, 8, 8),
new Tuple<int, int, int>(2, 8, 11),
new Tuple<int, int, int>(2, 3, 8),
new Tuple<int, int, int>(3, 9, 2),
new Tuple<int, int, int>(8, 9, 7),
new Tuple<int, int, int>(8, 7, 1),
new Tuple<int, int, int>(7, 9, 6),
new Tuple<int, int, int>(3, 4, 7),
new Tuple<int, int, int>(3, 6, 4),
new Tuple<int, int, int>(6, 7, 2),
new Tuple<int, int, int>(4, 6, 14),
new Tuple<int, int, int>(4, 5, 9),
new Tuple<int, int, int>(5, 6, 10)
},
37
},
new object[]
{
4,
new List<Tuple<int, int, int>>()
{
new Tuple<int, int, int>(1, 2, 4),
new Tuple<int, int, int>(1, 3, 1),
new Tuple<int, int, int>(1, 4, 2),
new Tuple<int, int, int>(2, 3, 6),
new Tuple<int, int, int>(2, 4, 1),
new Tuple<int, int, int>(3, 4, 7)
},
4
}
};
[TestCaseSource(nameof(TestCasesForKruskalsAlgorithm))]
public void TestKruskal_ShouldGetExpectedResult(int totalNodes, List<Tuple<int, int, int>> edges, int expected)
{
var result = Algorithms.Graph.KruskalsAlgorithm.KruskalDriver(totalNodes, edges);
var propertyInfo = result.GetType().GetProperty("weight");
var weight = propertyInfo.GetValue(result, null);
Assert.AreEqual(expected, weight);
}
}
}