public static void ShortestPath(SqlInt64 startNode, SqlInt64 endNode, SqlInt32 maxNodesToCheck, out SqlString pathResult, out SqlDouble distResult) { Dictionary <long, double> distance = new Dictionary <long, double>(); // curr shortest distance (double) from startNode to (key) node Dictionary <long, long> previous = new Dictionary <long, long>(); // predecessor values to construct the actual path when done Dictionary <long, bool> beenAdded = new Dictionary <long, bool>(); // has node been added to the queue yet? Once added, we don't want to add again long startNodeAsLong = (long)startNode; long endNodeAsLong = (long)endNode; int maxNodesToCheckAsInt = (int)maxNodesToCheck; MyPriorityQueue PQ = new MyPriorityQueue(); //initialize start node distance[startNodeAsLong] = 0.0; // distance from start node to itself is 0 previous[startNodeAsLong] = -1; // -1 is the code for undefined. PQ.Enqueue(new NodeDistance(startNodeAsLong, 0.0)); // the queue holds distance information because Enqueue and Dequeue need it to keep queue ordered by priority. alt approach would be to store only node IDs and then do a distance lookup beenAdded[startNodeAsLong] = true; double alt = 0.0; //'test distance' try { while (PQ.Count() > 0 && beenAdded.Count < maxNodesToCheckAsInt) { NodeDistance u = PQ.Dequeue();// node with shortest distance from start if (u.nodeID == endNode) { break;// found the target end node } //fetch all neighbors (v) of u List <Tuple <long, double> > neighbors = new List <Tuple <long, double> >(); neighbors = FetchNeighbors(u.nodeID); foreach (var v in neighbors) // if there are no neighbors, this loop will exit immediately { if (beenAdded.ContainsKey(v.Item1) == false) //first appearance of node v { distance[v.Item1] = double.MaxValue; //stand-in for infinity previous[v.Item1] = -1; //undefined PQ.Enqueue(new NodeDistance(v.Item1, double.MaxValue)); //maxValue is a dummy value beenAdded[v.Item1] = true; } //alt = distance[u.nodeID] + 1.0; // if all edge weights are just hops can simplify to this alt = distance[u.nodeID] + v.Item2; // alt = dist(start-to-u) + dist(u-to-v), so alt is total distance from start to v if (alt < distance[v.Item1]) // is alt a new, shorter distance from start to v? { distance[v.Item1] = alt; previous[v.Item1] = u.nodeID; PQ.ChangePriority(v.Item1, alt); // this will change the distance/priority } } } // extract the shortest path as a string from the previous[] array pathResult = "NOTREACHABLE"; // default result string distResult = -1.0; // distance result defaults to -1 == unreachable if (distance.ContainsKey(endNodeAsLong) == true) // endNode was encountered at some point in the algorithm { double sp = distance[endNodeAsLong]; // shortest path distance if (sp != double.MaxValue) // we have a reachable path { pathResult = ""; long currNode = endNodeAsLong; while (currNode != startNodeAsLong) // construct the path as semicolon delimited string { pathResult += currNode.ToString() + ";"; currNode = previous[currNode]; } pathResult += startNode.ToString(); // tack on the start node distResult = sp; // the distance result } } } catch (Exception ex) // typically Out Of Memory or a Command TimeOut { pathResult = ex.ToString(); distResult = -1.0; } }