【问题标题】:My Dijkstra algorithm's not choosing the shortes path我的 Dijkstra 算法没有选择最短路径
【发布时间】:2017-05-05 19:33:49
【问题描述】:

我尝试使用两个自定义顶点结构和它们的边为我的自定义图编写 Dijkstra 算法,该算法可以编译,但它在选择最佳距离时做出了错误的选择。代码如下。

class Graph {
struct Edge;
struct Vertex {
    std::string _data;  //name of vertex    
    std::list<Edge*> _ins;
    std::list<Edge*> _outs;
    bool visited;
    int BestDist;//best distance from source to sink

};
struct Edge {
    int _weight;
    Vertex *_from;
    Vertex *_to;
    bool travelled; //if the edge has been travalled
};
//Graph of String as key to Values as vertexes
std::unordered_map<std::string, Vertex *> _mainData; 

//Dijkstra Algo
int BestDistance(std::string source, std::string sink) {

    //to save vertexes names
    std::queue<std::string> q;

    //for each vertex set dist and path to infinity
    for (auto startItr : _mainData)
    {
        startItr.second->BestDist = Max;
        startItr.second->visited = false;
        for (auto kachal : startItr.second->_outs)
        {
            kachal->travelled = false;
        }
    }

    //set source distacne to 0 sicen it is visiting itself
    _mainData[source]->BestDist = 0;
    q.push(source);

    //while there is unknown distance vertex and we havent reach sink yet
    while (!q.empty() )
    {
        //smallest unknow distance vertex
        std::string currentVer = q.front(); q.pop();
        //set that vertex to visited
        _mainData[currentVer]->visited = true;

        //for each vertex adj to current vertex
        for (auto adjVer : _mainData[currentVer]->_outs) {
            //if that vertex is not visted
            if (!adjVer->travelled) {
                int cvw = adjVer->_weight; //cost of edge from cuurent vertex to adj vertex

                //if current vert.distance +cvw < adj vertex distance
                if (_mainData[currentVer]->BestDist + cvw < _mainData[adjVer->_to->_data]->BestDist) {
                    //update adj vertex
                    q.push(adjVer->_to->_data);
                    //deacrease adj vertex distacne  to current distacne + cvw
                    _mainData[adjVer->_to->_data]->BestDist = _mainData[currentVer]->BestDist + cvw;
                    //marked the travlled edge true
                    adjVer->travelled = true;
                }
            }
        }
    }
    return _mainData[sink]->BestDist;
}

这是我的主要内容:

 #include "stdafx.h"
 #include "Graph.h"
 #include <iostream>

int main()
 {
 Graph myGraph;
 myGraph.Add("A");
 myGraph.Add("B");
 myGraph.Add("C");
 myGraph.Add("D");
 myGraph.Add("E");
 myGraph.Add("F");
 myGraph.Add("G");

 myGraph.Connect("A", "B",20);
 myGraph.Connect("A", "C",30);
 myGraph.Connect("B", "D",200);
 myGraph.Connect("C", "F",100);
 myGraph.Connect("C", "G",200);
 myGraph.Connect("D", "E",50);
 myGraph.Connect("E", "F",1);
 myGraph.Connect("F", "G",30);
 std::cout << "best distacne example : " << myGraph.BestDistance("A", "G");

所以当我运行代码时,从 A 到 G 的最佳距离应该返回为 160 (A->C->F->G),但代码返回 280,即 (A->C->G) .我可以提供我的添加和连接功能,但我确信它们工作正常。

【问题讨论】:

  • Dijkstra 的算法运行良好,并且总是做出正确的选择。是你的错误实现算法不起作用。
  • 创建一个有两个节点的测试用例,看看它是否返回正确的值。然后 3...
  • @MikeNakis 是的,你是真的,对不起我的英语不好。目前我对 Dijkstra 的实现很糟糕。
  • @stark :大多数测试用例都可以正常工作,除非 Vertex 有两个或更多输入。在那种情况下,到达该顶点的任何方式都设置为最佳距离,我猜无论每条边的权重是多少
  • 天哪!你找到了一些东西。现在使用调试器或添加打印语句来找出问题所在。

标签: c++ algorithm queue graph-algorithm dijkstra


【解决方案1】:

所以在分析了上述算法后,我意识到我的错误是将每条边标记为是否经过,并据此做出决定。我应该做的是标记每个顶点是否被访问。其余的都可以。所以这是我在正加权图中找到最短路径的 Dijkstra 算法实现的正确版本。希望对你有帮助

//Dijkstra Algo
int BestDistance(std::string source, std::string sink) {

    //to save vertexes names
    std::queue<std::string> q;

    //for each vertex set dist and path to infinity
    for (auto startItr : _mainData)
    {
        startItr.second->BestDist = Max;
        startItr.second->visited = false;
    }

    //set source distacne to 0 sicen it is visiting itself
    _mainData[source]->BestDist = 0;

    q.push(source);

    //while there is unknown distance vertex and we havent reach sink yet
    while (!q.empty() )
    {
        //smallest unknow distance vertex
        std::string currentVer = q.front(); q.pop();

        //set that vertex to visited
        _mainData[currentVer]->visited = true;

        //for each vertex adj to current vertex
        for (auto adjVer : _mainData[currentVer]->_outs) {
            //if that vertex is not visted
            if (!adjVer->_to->visited) {
                int cvw = adjVer->_weight; //cost of edge from cuurent 
                                           //vertex to adj vertex

                //if current vert.distance +cvw < adj vertex distance
                if (_mainData[currentVer]->BestDist + cvw < 
                   _mainData[adjVer->_to->_data]->BestDist) {

                    q.push(adjVer->_to->_data);

                    //deacrease adj vertex distacne  to current distacne + cvw
                    _mainData[adjVer->_to->_data]->BestDist = _mainData[currentVer]->BestDist + cvw;
                    //setting the path of adj vertext to his previous one
                    _mainData[adjVer->_to->_data]->path = _mainData[currentVer]; 
                }
            }
        }
    }
    return _mainData[sink]->BestDist;
}

【讨论】:

  • 当然还有许多其他更好和优化的解决方案。我是编程新手,所以如果代码有缺陷,我深表歉意。我感谢任何关于如何使其更好或更高效的建议和 cmet
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多