public List <Edge> DijkstraShortestPath(Vertex source, Vertex destination = default) { var sp = new Dictionary <Vertex, Edge>(); if (!adjacencyList.Any()) { return(sp.Values.ToList()); } var vertexToPathCost = new Dictionary <Vertex, PathCost>(); // Min Heap storing accumulated min cost for reaching target node greedily var minHeapNodes = new IndexedHeap <PathCost>( new List <PathCost> { (vertexToPathCost[source] = new PathCost(source, 0)) }, compareFunc: (p1, p2) => p1.cost.CompareTo(p2.cost)); foreach (var vertex in adjacencyList.Keys) { if (vertex == source) { continue; } minHeapNodes.Push(vertexToPathCost[vertex] = new PathCost(vertex, int.MaxValue)); } // Greedy strategy: Select the path that minimized the accumulated cost up to this node // Traverse the node by min cost while (minHeapNodes.Any()) { var minNode = minHeapNodes.Pop(); // Visit all the neighbors and update the corresponding cost foreach (var edge in adjacencyList[minNode.vertex]) { // Check that the current cost of reaching the adjacent node is less than the current one if (minHeapNodes.Contains(vertexToPathCost[edge.destination]) && minNode.cost + edge.weight < vertexToPathCost[edge.destination].cost) { vertexToPathCost[edge.destination].cost = minNode.cost + edge.weight; sp[edge.destination] = edge; // Sift up the heap starting from the current index (log n) minHeapNodes.SiftUp(fromIndex: minHeapNodes.IndexOf(vertexToPathCost[edge.destination])); } } if (minNode.vertex.Equals(destination)) { break; } } return(sp.Values.ToList()); }
public List <Edge> PrimsMinimumSpanningTree() { var mst = new Dictionary <Vertex, Edge>(); if (!adjacencyList.Any()) { return(mst.Values.ToList()); } var vertexToMinCost = new Dictionary <Vertex, PathCost>(); // Min Heap storing min cost of the spanning tree var minHeapNodes = new IndexedHeap <PathCost>( new List <PathCost> { (vertexToMinCost[adjacencyList.Keys.First()] = new PathCost(adjacencyList.Keys.First(), 0)) }, (p1, p2) => p1.cost.CompareTo(p2.cost)); foreach (var vertex in adjacencyList.Keys.Skip(1)) { minHeapNodes.Push(vertexToMinCost[vertex] = new PathCost(vertex, int.MaxValue)); } // Traverse the node by min cost // Greedy strategy: Select the edge that minimize the cost for reaching node from its neighbors while (minHeapNodes.Any()) { var minNode = minHeapNodes.Pop(); // Visit all the neighbors and update the corresponding cost foreach (var edge in adjacencyList[minNode.vertex]) { // Check that the current cost of reaching the adjacent node is less than the current one if (minHeapNodes.Contains(vertexToMinCost[edge.destination]) && edge.weight < vertexToMinCost[edge.destination].cost) { vertexToMinCost[edge.destination].cost = edge.weight; mst[edge.destination] = edge; // Sift up the heap starting from the current index (log n) minHeapNodes.SiftUp(fromIndex: minHeapNodes.IndexOf(vertexToMinCost[edge.destination])); } } } return(mst.Values.ToList()); }