/// <summary> /// Dijkstras algorithm that traverses the graph to find shortest path /// </summary> /// <param name="graph"> <see cref="Graph"/> instance. </param> /// <param name="startVertex"> The start <see cref="Vertex"/> of path to calculate minimum distance for. </param> /// <returns> The shortest (minimum cost) path from starting point to all other. </returns> public static PathwayCollection <T> Dijkstra <T>(this DirectedGraph <T> graph, Vertex <T> startVertex) where T : IEquatable <T> { var distances = graph.Vertices.ToDictionary(key => key, value => long.MaxValue); distances[startVertex] = 0; var distancesMinimumHeap = new BinaryHeap <VertexDistancePair <T> >( BinaryHeapType.MinimumHeap, graph.Vertices.Count, new VertexDistancePairComparer <T>()); distancesMinimumHeap.Add(new VertexDistancePair <T>(startVertex, 0)); var pathVertices = new Dictionary <Vertex <T>, Vertex <T> >(); while (distancesMinimumHeap.Count > 0) { var shortestDistanceVertexPair = distancesMinimumHeap.Remove(); var shortestDistanceVertex = shortestDistanceVertexPair.Vertex; foreach (var outboundEdge in shortestDistanceVertex.OutboundEdges) { var outboundEndVertex = outboundEdge.EndVertex; long alternativeDistance = distances[shortestDistanceVertex] + outboundEdge.Weight; if (alternativeDistance < distances[outboundEndVertex]) { distances[outboundEndVertex] = alternativeDistance; pathVertices[outboundEndVertex] = shortestDistanceVertex; distancesMinimumHeap.Add(new VertexDistancePair <T>(outboundEndVertex, alternativeDistance)); } } } return(new PathwayCollection <T>(pathVertices, distances, startVertex)); }
/// <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)); }