/// <summary> /// Traverses graph from start vertex. /// </summary> /// <param name="graph">Graph instance.</param> /// <param name="startVertex">Vertex that search starts from.</param> /// <param name="action">Action that needs to be executed on each graph vertex.</param> /// <param name="visited">Hash set with visited vertices.</param> private void Bfs(IDirectedWeightedGraph <T> graph, Vertex <T> startVertex, Action <Vertex <T> >?action, HashSet <Vertex <T> > visited) { var queue = new Queue <Vertex <T> >(); queue.Enqueue(startVertex); while (queue.Count > 0) { var currentVertex = queue.Dequeue(); if (currentVertex == null || visited.Contains(currentVertex)) { continue; } foreach (var vertex in graph.GetNeighbors(currentVertex)) { queue.Enqueue(vertex !); } action?.Invoke(currentVertex); visited.Add(currentVertex); } }
/// <summary> /// Traverses graph from start vertex. /// </summary> /// <param name="graph">Graph instance.</param> /// <param name="startVertex">Vertex that search starts from.</param> /// <param name="action">Action that needs to be executed on each graph vertex.</param> /// <param name="visited">Hash set with visited vertices.</param> private void Dfs(IDirectedWeightedGraph <T> graph, Vertex <T> startVertex, Action <Vertex <T> >?action, HashSet <Vertex <T> > visited) { action?.Invoke(startVertex); visited.Add(startVertex); foreach (var vertex in graph.GetNeighbors(startVertex)) { if (vertex == null || visited.Contains(vertex)) { continue; } Dfs(graph, vertex !, action, visited); } }
// X - set of explored vertices of graph G // V-X - set of unexplored vertices of graph G // // Invariant. // The key of a vertex w belongs to V-X is the min Dijkstra score of an edge with tail v belongs to X // and head w, or +infinity if no such edge exists. // key(w) = min len(v) + l(vw) // // DijkstraSearch(graph G, vertex s): // // Initialization // X = empty set // H = empty min heap // key(s) = 0 // for each vertex V in G.vertices do: key(V) = +infinity // for each vertex V in G.vertices do: H.Insert(V) // // Main loop // while H is not empty do: // w* = H.ExtractMin() // X.Add(w*) // len(w*) = key(w*) // // Update Heap to maintain Invariant // for every edge(w*, y) do: // H.Delete(y) // Delete: given a heap H and a pointer to an object y in H, delete y from H. // key(y) = min {key(y), len(w*) + l(w*y)} // H.Insert(y) public static int[] DijkstraMinHeap(IDirectedWeightedGraph <int> weightedGraph, int startVertex) { var minHeap = new IndexMinHeap <int>(weightedGraph.VerticesCount); var exploredVertices = new HashSet <int> { startVertex }; var len = new int[weightedGraph.VerticesCount + 1]; for (int i = 1; i <= weightedGraph.VerticesCount; i++) { var score = i == startVertex ? 0 : 1000000; len[i] = score; minHeap.Insert(i, score); } while (!minHeap.IsEmpty()) { int u = minHeap.GetMin(); len[u] = minHeap.GetItemKey(u); minHeap.ExtractMin(); exploredVertices.Add(u); foreach ((int v, int weight) in weightedGraph.GetAdjacentVertices(u)) { if (!exploredVertices.Contains(v)) { if (len[v] > len[u] + weight) { int vKey = minHeap.GetItemKey(v); int newScore = Math.Min(len[u] + weight, vKey); // can use (minHeap.Delete + minHeap.Insert) instead of DecreaseKey // but this would be less effective minHeap.DecreaseKey(v, newScore); len[v] = newScore; } } } } return(len); }
/// <summary> /// Traverses graph from start vertex. /// </summary> /// <param name="graph">Graph instance.</param> /// <param name="startVertex">Vertex that search starts from.</param> /// <param name="action">Action that needs to be executed on each graph vertex.</param> public void VisitAll(IDirectedWeightedGraph <T> graph, Vertex <T> startVertex, Action <Vertex <T> >?action = default) { Dfs(graph, startVertex, action, new HashSet <Vertex <T> >()); }
private static (int vertex, int weight) FindMinWeightVertex(IDirectedWeightedGraph <int> weightedGraph, (int tail, int head, int weight) edge)