C# Dijkstra困难';s算法

C# Dijkstra困难';s算法,c#,dijkstra,vertex,C#,Dijkstra,Vertex,我不熟悉高级算法,所以请耐心听我说。我目前正在尝试让Dijkstra的算法工作,并且花了2天的时间试图解决这个问题。我还阅读了维基百科上的伪代码,并取得了这一成果。我想得到两个顶点之间的最短距离。在下面的示例中,我一直得到错误的距离。请帮忙 图形设置示例如下所示: Graph graph = new Graph(); graph.Vertices.Add(new Vertex("A")); graph.Vertices.Add(new Vertex("B")); graph.Vertices.A

我不熟悉高级算法,所以请耐心听我说。我目前正在尝试让Dijkstra的算法工作,并且花了2天的时间试图解决这个问题。我还阅读了维基百科上的伪代码,并取得了这一成果。我想得到两个顶点之间的最短距离。在下面的示例中,我一直得到错误的距离。请帮忙

图形设置示例如下所示:

Graph graph = new Graph();
graph.Vertices.Add(new Vertex("A"));
graph.Vertices.Add(new Vertex("B"));
graph.Vertices.Add(new Vertex("C"));
graph.Vertices.Add(new Vertex("D"));
graph.Vertices.Add(new Vertex("E"));

graph.Edges.Add(new Edge
                    {
                        From = graph.Vertices.FindVertexByName("A"),
                        To = graph.Vertices.FindVertexByName("B"),
                        Weight = 5
                    });

graph.Edges.Add(new Edge
                    {
                        From = graph.Vertices.FindVertexByName("B"),
                        To = graph.Vertices.FindVertexByName("C"),
                        Weight = 4
                    });

graph.Edges.Add(new Edge
                    {
                        From = graph.Vertices.FindVertexByName("C"),
                        To = graph.Vertices.FindVertexByName("D"),
                        Weight = 8
                    });


graph.Edges.Add(new Edge
                    {
                        From = graph.Vertices.FindVertexByName("D"),
                        To = graph.Vertices.FindVertexByName("C"),
                        Weight = 8
                    });

//graph is passed as param with source and dest vertices
public int Run(Graph graph, Vertex source, Vertex destvertex)
{
    Vertex current = source;
    List<Vertex> queue = new List<Vertex>();

    foreach (var vertex in graph.Vertices)
    {
        vertex.Weight = int.MaxValue;
        vertex.PreviousVertex = null;
        vertex.State = VertexStates.UnVisited;
        queue.Add(vertex);
    }

    current = graph.Vertices.FindVertexByName(current.Name);
    current.Weight = 0;
    queue.Add(current);
    while (queue.Count > 0)
    {
        Vertex minDistance = queue.OrderBy(o => o.Weight).FirstOrDefault();
        queue.Remove(minDistance);

        if (current.Weight == int.MaxValue)
        {
            break;
        }

        minDistance.Neighbors = graph.GetVerTextNeigbours(current);

        foreach (Vertex neighbour in minDistance.Neighbors)
        {
            Edge edge = graph.Edges.FindEdgeByStartingAndEndVertex(minDistance, neighbour);
            int dist = minDistance.Weight + (edge.Weight);
            if (dist < neighbour.Weight)
            {
                //from this point onwards i get stuck
                neighbour.Weight = dist;
                neighbour.PreviousVertex = minDistance;
                queue.Remove(neighbour);
                queueVisited.Enqueue(neighbor);
            }
        }
        minDistance.State = VertexStates.Visited;
    }

      //here i want to record all node that was visited
     while (queueVisited.Count > 0)
    {
        Vertex temp = queueVisited.Dequeue();
        count += temp.Neighbors.Sum(x => x.Weight);
    }

    return count;
}
Graph-Graph=new-Graph();
添加(新顶点(“A”));
添加(新顶点(“B”));
添加(新顶点(“C”));
添加(新顶点(“D”);
添加(新顶点(“E”);
图.边.添加(新边)
{
From=graph.Vertices.FindVertexByName(“A”),
To=graph.Vertices.FindVertexByName(“B”),
重量=5
});
图.边.添加(新边)
{
From=graph.vertexts.FindVertexByName(“B”),
To=graph.Vertices.FindVertexByName(“C”),
重量=4
});
图.边.添加(新边)
{
From=graph.Vertices.FindVertexByName(“C”),
To=graph.Vertices.FindVertexByName(“D”),
重量=8
});
图.边.添加(新边)
{
From=graph.Vertices.FindVertexByName(“D”),
To=graph.Vertices.FindVertexByName(“C”),
重量=8
});
//图形作为带有源和目标顶点的参数传递
公共整型运行(图形、顶点源、顶点终止顶点)
{
顶点电流=源;
列表队列=新列表();
foreach(图中的var顶点。顶点)
{
顶点权重=int.MaxValue;
vertex.PreviousVertex=null;
vertex.State=VertexStates.UnVisited;
添加(顶点);
}
current=graph.vertexts.FindVertexByName(current.Name);
当前权重=0;
queue.Add(当前);
而(queue.Count>0)
{
Vertex minDistance=queue.OrderBy(o=>o.Weight).FirstOrDefault();
队列。移除(minDistance);
if(current.Weight==int.MaxValue)
{
打破
}
minDistance.Neighbors=graph.GetVerTextNeigbours(当前);
foreach(minDistance.neights中的顶点邻居)
{
Edge Edge=graph.Edges.通过StartingAndVertex(minDistance,Neighbor)查找;
int dist=minDistance.Weight+(edge.Weight);
if(距离<相邻重量)
{
//从这一点开始,我就陷入困境
邻居。重量=距离;
nexter.PreviousVertex=思维距离;
排队。移除(邻居);
queueVisited.Enqueue(邻居);
}
}
minDistance.State=顶点状态。已访问;
}
//在这里,我想记录访问的所有节点
而(queuevisted.Count>0)
{
顶点温度=queueVisited.Dequeue();
计数+=临时邻居和(x=>x.Weight);
}
返回计数;
}

上述代码存在几个直接问题

  • current
    变量永远不会重新赋值,对象也不会发生变化,因此
    graph.GetVerTextNeigbours(current)
    始终返回相同的集合

    因此,如果必须遍历多条边,则甚至无法找到目标顶点

  • 邻居节点通过
    队列从队列中删除。删除(邻居)
    。这是不正确的,可能会阻止对节点/顶点进行[重新]探索。相反,它应该只更新队列中的权重

    在这种情况下,“Q中的减少密钥v”是由于对象突变和未使用优先级队列(即排序)结构而导致实现中无操作的psuedo代码

  • 根据
    queueVisited.Enqueue(neighbor)
    和后面的“所有访问节点的所有邻居权重之和”,访问的队列不正确

    算法运行后,所探索的任何节点/顶点的成本(
    权重
    )是到该顶点的最短路径的成本。因此,您可以简单地询问目标顶点的成本是多少


  • 此外,为了简化算法,我建议放弃最初创建的“图/顶点/边”布局,而是传入一个简单节点。这个节点可以枚举它的邻居节点,知道每个邻居的权重、它自己的当前权重以及它的最佳成本节点


    只需在开始时构建一次此节点图,然后传递开始节点。这消除了(或大大简化)调用,例如“代码> GETVBETCHORIONS 和<代码> FieldGeByEngestIdand EndothEX/CODE >,以及奇怪的/不必要的副作用,例如每次代码访问顶点时分配<代码>邻居< /代码>。< /P>切线:考虑优先级队列(或二进制堆).minDistance是具有最小权重的顶点。第12行的伪代码。