-
Notifications
You must be signed in to change notification settings - Fork 299
/
Copy pathKruskals.cs
121 lines (98 loc) · 3.79 KB
/
Kruskals.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Collections.Generic;
using Advanced.Algorithms.DataStructures;
using Advanced.Algorithms.DataStructures.Graph;
using Advanced.Algorithms.Sorting;
namespace Advanced.Algorithms.Graph;
/// <summary>
/// A Kruskal's alogorithm implementation
/// using merge sort and disjoint set.
/// </summary>
public class Kruskals<T, TW> where TW : IComparable
{
/// <summary>
/// Find Minimum Spanning Tree of given weighted graph.
/// </summary>
/// <returns>List of MST edges</returns>
public List<MstEdge<T, TW>>
FindMinimumSpanningTree(IGraph<T> graph)
{
var edges = new List<MstEdge<T, TW>>();
//gather all unique edges
Dfs(graph.ReferenceVertex, new HashSet<T>(),
new Dictionary<T, HashSet<T>>(),
edges);
//quick sort preparation
var sortArray = new MstEdge<T, TW>[edges.Count];
for (var i = 0; i < edges.Count; i++) sortArray[i] = edges[i];
//quick sort edges
var sortedEdges = MergeSort<MstEdge<T, TW>>.Sort(sortArray);
var result = new List<MstEdge<T, TW>>();
var disJointSet = new DisJointSet<T>();
//create set
foreach (var vertex in graph.VerticesAsEnumberable) disJointSet.MakeSet(vertex.Key);
//pick each edge one by one
//if both source and target belongs to same set
//then don't add the edge to result
//otherwise add it to result and union sets
for (var i = 0; i < edges.Count; i++)
{
var currentEdge = sortedEdges[i];
var setA = disJointSet.FindSet(currentEdge.Source);
var setB = disJointSet.FindSet(currentEdge.Destination);
//can't pick edge with both ends already in MST
if (setA.Equals(setB)) continue;
result.Add(currentEdge);
//union picked edge vertice sets
disJointSet.Union(setA, setB);
}
return result;
}
/// <summary>
/// Do DFS to find all unique edges.
/// </summary>
private void Dfs(IGraphVertex<T> currentVertex, HashSet<T> visitedVertices, Dictionary<T, HashSet<T>> visitedEdges,
List<MstEdge<T, TW>> result)
{
if (!visitedVertices.Contains(currentVertex.Key))
{
visitedVertices.Add(currentVertex.Key);
foreach (var edge in currentVertex.Edges)
{
if (!visitedEdges.ContainsKey(currentVertex.Key)
|| !visitedEdges[currentVertex.Key].Contains(edge.TargetVertexKey))
{
result.Add(new MstEdge<T, TW>(currentVertex.Key, edge.TargetVertexKey, edge.Weight<TW>()));
//update visited edge
if (!visitedEdges.ContainsKey(currentVertex.Key))
visitedEdges.Add(currentVertex.Key, new HashSet<T>());
visitedEdges[currentVertex.Key].Add(edge.TargetVertexKey);
//update visited back edge
if (!visitedEdges.ContainsKey(edge.TargetVertexKey))
visitedEdges.Add(edge.TargetVertexKey, new HashSet<T>());
visitedEdges[edge.TargetVertexKey].Add(currentVertex.Key);
}
Dfs(edge.TargetVertex, visitedVertices, visitedEdges, result);
}
}
}
}
/// <summary>
/// Minimum spanning tree edge object.
/// </summary>
public class MstEdge<T, TW> : IComparable where TW : IComparable
{
internal MstEdge(T source, T dest, TW weight)
{
Source = source;
Destination = dest;
Weight = weight;
}
public T Source { get; }
public T Destination { get; }
public TW Weight { get; }
public int CompareTo(object obj)
{
return Weight.CompareTo(((MstEdge<T, TW>)obj).Weight);
}
}