Dijkstra的算法 - 初始化节点距离

时间:2014-12-09 03:57:44

标签: c++ algorithm data-structures dijkstra

我有一项任务是使用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);
          }
        }
      }
    }
  }
}

谢谢!

2 个答案:

答案 0 :(得分:1)

你错过了这一步:

Vertex v = smallest unknown distance vertex;

而是循环遍历所有顶点。

到起始顶点的距离初始化为0,因此如果您实现算法的这一部分并选择距离最小但不是“已知”的v,您将从启动开始顶点和if应该有效。

替换:

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);
  ...
}

答案 1 :(得分:0)

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

实施

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

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

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

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

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