/// <summary> /// Prim's algorithm to find the minimum span tree on graph /// </summary> /// <param name="graph"> <see cref="Graph"/> instance. </param> /// <returns> Minimum span tree containing edges and minimum distance. </returns> public static MinimumSpanTree <T> PrimsMinimumSpanningTree <T>(this DirectedGraph <T> graph) where T : IEquatable <T> { if (graph.Vertices.Count == 0 || graph.Edges.Count == 0) { return(new MinimumSpanTree <T>(Enumerable.Empty <Edge <T> >().ToList(), 0)); } var currentVertex = graph.Vertices.First(); int minimumDistance = 0; var minimumSpanTree = new List <Edge <T> >(); var edgesToVisit = new BinaryHeap <Edge <T> >(BinaryHeapType.MinimumHeap, currentVertex.OutboundEdges.Count, new EdgeComparer <T>()); var verticesVisited = new HashSet <Vertex <T> >(); while (minimumSpanTree.Count < graph.Vertices.Count - 1) { foreach (var edge in currentVertex.OutboundEdges) { edgesToVisit.Add(edge); } verticesVisited.Add(currentVertex); Edge <T> minimumEdge = null; while (edgesToVisit.Count > 0) { minimumEdge = edgesToVisit.Remove(); if (verticesVisited.Contains(minimumEdge.StartVertex) != verticesVisited.Contains(minimumEdge.EndVertex)) { break; } } if (minimumEdge == null) { throw new MultipleMinimumSpanningTreesException(); } minimumSpanTree.Add(minimumEdge); minimumDistance += minimumEdge.Weight; currentVertex = verticesVisited.Contains(minimumEdge.EndVertex) ? minimumEdge.StartVertex : minimumEdge.EndVertex; } return(new MinimumSpanTree <T>(minimumSpanTree, minimumDistance)); }
/// <summary> /// Kruskal's algorithm to find the minimum span tree on graph /// </summary> /// <param name="graph"> <see cref="Graph"/> instance. </param> /// <returns> Minimum span tree containing edges and minimum distance. </returns> public static MinimumSpanTree <T> KruskalsMinimumSpanningTree <T>(this DirectedGraph <T> graph) where T : IEquatable <T> { if (graph.Vertices.Count == 0 || graph.Edges.Count == 0) { return(new MinimumSpanTree <T>(Enumerable.Empty <Edge <T> >().ToList(), 0)); } var minimumSpanTree = new List <Edge <T> >(); var minimumDistance = 0; var unionFind = new DisjointSet <Vertex <T> >(graph.Vertices); var edgesToVisit = new BinaryHeap <Edge <T> >(BinaryHeapType.MinimumHeap, graph.Edges.Count, new EdgeComparer <T>()); foreach (var edge in graph.Edges) { edgesToVisit.Add(edge); } while (minimumSpanTree.Count < graph.Vertices.Count - 1) { Edge <T> minimumEdge = null; while (edgesToVisit.Count > 0) { minimumEdge = edgesToVisit.Remove(); if (unionFind.Find(minimumEdge.StartVertex) != unionFind.Find(minimumEdge.EndVertex)) { break; } } if (minimumEdge == null) { throw new MultipleMinimumSpanningTreesException(); } minimumSpanTree.Add(minimumEdge); minimumDistance += minimumEdge.Weight; unionFind.Union(minimumEdge.StartVertex, minimumEdge.EndVertex); } return(new MinimumSpanTree <T>(minimumSpanTree, minimumDistance)); }