【发布时间】:2023-03-30 06:39:02
【问题描述】:
我目前已经实现了 Dijkstra 的算法,但是当我用这样的图表测试我的算法时出现了问题:
并尝试从 C 转到 B。我知道为什么它不起作用。但我想知道如果有这样的图表,正常的实现是否可行?
internal static Stack<string> Dijkstra(string sourcePoint, string targetPoint, Graph graph)
{
List<string> verticesStringList = graph.GetAllVertices();
Dictionary<string, Vertex> verticesDictionary = new Dictionary<string, Vertex>();
InitializeVerticesDictionary(sourcePoint, verticesStringList, verticesDictionary);
while (verticesDictionary.Values.ToList().Any(x => x.IsVisited == false))
{
KeyValuePair<string, Vertex> keyValuePair = verticesDictionary.Where(x => x.Value.IsVisited == false).ToList().Min();
string vertexKey = keyValuePair.Key;
Vertex currentVertex = keyValuePair.Value;
List<string> neighbourVertices = graph.GetNeighbourVerticesSorted(keyValuePair.Key);
foreach (string neighbourVertexString in neighbourVertices)
{
Vertex neighbourVertex = verticesDictionary[neighbourVertexString];
int newDistanceFromStartVertex = currentVertex.ShortestDistanceFromTarget + graph.GetEdgeWeight(keyValuePair.Key, neighbourVertexString);
if (newDistanceFromStartVertex < neighbourVertex.ShortestDistanceFromTarget)
{
verticesDictionary[neighbourVertexString].ShortestDistanceFromTarget = newDistanceFromStartVertex;
verticesDictionary[neighbourVertexString].PreviousVertex = keyValuePair.Key;
}
}
verticesDictionary[vertexKey].IsVisited = true;
}
return FormShortestPath(targetPoint, verticesDictionary);
}
private static Stack<string> FormShortestPath(string targetPoint, Dictionary<string, Vertex> verticesDictionary)
{
Stack<string> traverseStack = new Stack<string>();
KeyValuePair<string, Vertex> vertex = verticesDictionary.Where(x => x.Key == targetPoint).FirstOrDefault();
while (vertex.Value.PreviousVertex != null)
{
traverseStack.Push(vertex.Value.PreviousVertex + " Goes To " + vertex.Key); //the end edge
vertex = verticesDictionary.Where(x => x.Key == vertex.Value.PreviousVertex).FirstOrDefault();
}
return traverseStack;
}
private static void InitializeVerticesDictionary(string sourcePoint, List<string> verticesStringList, Dictionary<string, Vertex> verticesDictionary)
{
foreach (string vertexString in verticesStringList)
{
Vertex vertex = new Vertex
{
ShortestDistanceFromTarget = int.MaxValue
};
if (vertexString == sourcePoint)
{
vertex.ShortestDistanceFromTarget = 0;
}
verticesDictionary.Add(vertexString, vertex);
}
}
更新:我将条件更改为 verticesDictionary.Values.ToList().Any(x => x.IsVisited == false && x.ShortestDistanceFromTarget != int.MaxValue),现在我没有遇到我在 cmets 中提到的溢出。
【问题讨论】:
-
不起作用是什么意思?如果您在处理目标节点时使用 while(true) 并中断,那就是问题所在。将 while true 更改为 while(有一些事情要处理) 将解决它
-
@juvian 我实际上正在使用您提到的第二种方法。节点的实际处理不是问题。当我回溯已处理的节点时,问题就来了
-
只有在实际到达该节点时才应回溯,因为没有路径就没有路径
-
@juvian 目前我的伪代码代码是 while (collection contains an unvisited node){//logic currentNode.IsVisited=true}... 循环完成后我开始从结束到开始。那么我怎么知道是否没有通往它的路径呢?
-
检查目标节点的IsVisited是否为真?
标签: c# algorithm graph graph-algorithm dijkstra