/// <summary> /// Returns the shortest distances and paths between all vertexes. /// </summary> /// <returns>Shortest distances and paths.</returns> public (int?[, ] distance, int[, ] next) GetResult() { var n = m_weights.VertexCount; var d = new int?[n, n]; var next = new int[n, n]; // Initialization. for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { d[i, j] = m_weights[i, j]; next[i, j] = j; } } for (int k = 0; k < n; ++k) { for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (m_cmp.Compare(d[i, j], d[i, k] + d[k, j]) > 0) { d[i, j] = d[i, k] + d[k, j]; next[i, j] = next[i, k]; } } } } return(d, next); }
/// <summary> /// Returns the shortest distances and paths between <see cref="source" /> vertex ant other vertexes. /// </summary> /// <param name="source">Source vertex.</param> /// <returns>Shortest distances and paths.</returns> /// <exception cref="ArgumentOutOfRangeException">: source less than 0 or greater than or equal the graph vertext count.</exception> public IReadOnlyList <Vertex> GetResult(int source) { var n = m_weights.VertexCount; if (source < 0 || source >= n) { throw new ArgumentOutOfRangeException(nameof(source)); } // Distances and paths. var result = new Vertex[n]; // Visited vertexes. var visitedVertexes = new bool[n]; // Binary heap to search vertex with min distance. var binaryHeap = m_weights is SparseGraph <int?> ?new BinaryHeap <(int v, int?d)>(new BinaryHeapComparer()) : null; // Returns from the intermediate result a vertex with a min distance from the source vertex to it. int GetMinFromIntermediateResult() { var minIndex = -1; var minDistance = INF; for (var i = 0; i < n; i++) { if (!visitedVertexes[i] && (minIndex == -1 || m_cmp.Compare(minDistance, result[i].Distance) > 0)) { minIndex = i; minDistance = result[i].Distance; } } return(minIndex); } // Returns from the binary heap a vertex with a min distance from the source vertex to it. int GetMinFromBinaryHeap() { return(binaryHeap.Count == 0 ? -1 : binaryHeap.Pop().v); } var getMin = binaryHeap == null ? GetMinFromIntermediateResult : (Func <int>)GetMinFromBinaryHeap; // Initialization. for (var i = 0; i < n; i++) { if (i == source) { // The distance from the source vertex to itself is 0. result[i] = new Vertex(0); } else { // The distance from the source vertex to each other vertex is infinity. result[i] = new Vertex(INF); } } binaryHeap?.Push((source, 0)); while (true) { // 'min' is not-visited vertex with a shortest distance from the source vertex. var min = getMin(); if (min == -1) { // If not found work is done. break; } // Mark 'min' as visited. visitedVertexes[min] = true; foreach (var neighbor in m_weights.GetNeighbors(min)) { if (neighbor.Value == INF) { // Vertexes are not connected. continue; } if (visitedVertexes[neighbor.Number]) { // Neighbor is visited. continue; } // Alternate distance from the source vertex to the neighbor of 'min'. var altDistance = result[min].Distance + neighbor.Value; // Changing distance to the neighbor if a shorter path found. if (m_cmp.Compare(result[neighbor.Number].Distance, altDistance) > 0) { result[neighbor.Number].Distance = altDistance; result[neighbor.Number].Previous = min; binaryHeap?.Push((neighbor.Number, altDistance)); } } } return(result); }