【问题标题】:Dijkstra's Algorithm - Initializing Node DistancesDijkstra 算法 - 初始化节点距离
【发布时间】:2014-12-09 03:57:43
【问题描述】:

我的任务是使用 Dijkstra 的最短路径算法进行简单的网络模拟。编码实现的一部分我不明白,这让我很伤心。 我搜索了堆栈溢出,发现了许多关于 Dijkstra 的有用问题,但没有针对我的具体问题。如果我没有进行足够深入的研究,我深表歉意。

我正在使用 Mark Allen Weiss 的 C++ 中的数据结构和算法分析中的伪代码:

void Graph::dijkstra( Vertex s)
{
    for each Vertex v
    {
        v.dist = INFINITY;
        v.known = false;
    }

    s.dist = 0;

    while( there is an unknown distance vertex )
    {
         Vertex v = smallest unknown distance vertex;
         v.known = true;

         for each Vertex w adjacent to v
         {
             if (!w.known)
             {
                 int cvw = cost of edge from v to w;
                 if(v.dist + cvw < w.dist)
                 {
                      //update w
                      decrease(w.dist to v.dist + cvw);
                      w.path = v;
                 }
             }

     }
}

除了最后一个if 语句之外,我的实现似乎还有效。

if(v.dist + cvw < w.dist)

我的代码永远不会进入下面的内容,因为每个节点的距离都被初始化为(基本上)无穷大,并且算法似乎永远不会改变距离。因此,比较的左侧永远不会小于右侧。我怎么会误解这个?

这是我的(凌乱的)代码:

class Vertex
{
private:
  int id;
  unordered_map < Vertex*, int > edges;
  int load_factor;
  int distance;
  bool known;
public:
        //getters and setters
};

void dijkstra(Vertex starting_vertex)
{
  for (int i = 0; i < vertices.size(); i++)
  {
    //my program initially stores vertices in the vertex in spot (id - 1).

    if (vertices[i].get_id() == starting_vertex.get_id())
    {
      vertices[i].set_distance(0);
      vertices[i].set_known(true);
    }
    else
    {
      vertices[i].set_distance(10000000);
      vertices[i].set_known(false);
    }
  }

  for (int i = 0; i < vertices.size(); i++)
  {
    //while there is an unknown distance vertex
    if (vertices[i].is_known() == false)
    {
      vertices[i].set_known(true);

      //for every vertex adjacent to this vertex
      for (pair<Vertex*, int> edge : vertices[i].get_edges())
      {
        //if the vertex isn't known
        if (edge.first->is_known() == false)
        {
          //calculate the weight using Adam's note on dijkstra's algorithm
          int weight = edge.second * edge.first->get_load_factor();

          if (vertices[i].get_distance() + weight < edge.first->get_distance())
          //this is my problem line. The left side is never smaller than the right.
          {
            edge.first->set_distance(vertices[i].get_distance() + weight);
            path.add_vertex(edge.first);
          }
        }
      }
    }
  }
}

谢谢!

【问题讨论】:

    标签: c++ algorithm data-structures dijkstra


    【解决方案1】:

    你错过了这一步:

    Vertex v = smallest unknown distance vertex;
    

    而是循环遍历所有顶点。

    到起始顶点的距离被初始化为0,因此如果您实现这部分算法并选择具有“未知”最小距离的v,您将从起始顶点和@开始987654324@ 应该可以工作。

    替换:

    for (int i = 0; i < vertices.size(); i++)
    {
      //while there is an unknown distance vertex
      if (vertices[i].is_known() == false)
      {
        ...
      }
    }
    

    类似的东西:

    while(countNumberOfUnknownVertices(vertices) > 0)
    {
      Vertex& v = findUnknownVertexWithSmallestDistance(vertices);
      ...
    }
    

    【讨论】:

      【解决方案2】:

      您错过了 Dijkstra 算法的两个重要部分。

      实施中

      while( there is an unknown distance vertex )
      {
          Vertex v = smallest unknown distance vertex;
      

      你将 v 设置为 第一个 你来到的未知顶点。它应该是所有未知顶点中距离最短的那个。

      另一个错误是,不是遍历顶点并对找到的每个未知顶点进行一些工作,而是需要在完成工作后再次搜索。

      例如,如果在一次迭代中,您从顶点 5 向外扩展,则可能会使顶点 3 成为距离最短的新未知顶点。您不能只从 5 开始继续搜索。

      除非您开发一些数据结构(也许是堆)来加快搜索速度,否则搜索距离最短的未知顶点会很慢。继续进行现在的线性搜索。 Dijkstra 的算法仍然有效,但需要时间 O(N^2)。您应该能够将其降低到至少 O(N log N)。

      【讨论】:

        猜你喜欢
        • 2013-11-18
        • 2020-08-02
        • 2017-09-15
        • 1970-01-01
        • 1970-01-01
        • 2020-12-08
        • 1970-01-01
        • 1970-01-01
        • 2014-06-09
        相关资源
        最近更新 更多