试图通过一个简单的例子来理解Dijkstra算法是如何工作的

时间:2013-07-30 01:07:22

标签: algorithm graph-algorithm dijkstra

我希望通过较短的路线(最低费用)从ad

  1    15
a--->b---->d
|        /\
|2       /
|       /1
|      /
|     /
|    /
|   /
|  /
| /
\/
c

a可以1美元或b费用2转到cb可以15美元的价格转到dc可以1美元的价格转到d

算法不会以a->b开头,因为它的成本为1而a->c成本为2吗?但是它只能从b->d开始,费用为15,这比a->c->d

的费用更高。

我正在努力梳理这个算法,所以请告诉我我的逻辑是否存在缺陷。

4 个答案:

答案 0 :(得分:1)

在第一步中找到节点与'a'的暂定距离,即s(b)= 1且s(c)= 2

队列 - > s(b)= 1,s(c)= 2

现在我们得到b的优先级队列,所以再次计算暂定距离s(d)= 16

队列 - > s(c)= 2,s(d)= 16

现在我们得到c,所以从c,s(d)= 3>计算暂定距离。先前的值s(d)= 17

所以最短的距离是3

答案 1 :(得分:1)

错误是认为“第一种方式,最好的方式”,这不是真的。在此算法中,您可以更新到达顶点的成本(如果由较低的成本保证)。

节点分为已访问,未访问,可用,不可用。

我们不能考虑被访问,因为如果他具有最小的值,并且我们没有负值边缘(参见算法假设),则找不到更好的方法。

Unvisited是另一种,可能我们实际上无法走向所有这些。

可用的顶点都是未访问的,我们现在可以访问它们。 (我认为,不可用是显而易见的。)

开始时只有第一个顶点。我们可以遵循一个简单的模式。

一步一步:

- 从所有(实际)可用的最便宜的顶点获取。这应该由优先级队列完成。最简单的解决方案是二进制堆( O(| E | log | V |)),但如果考虑性能,可以使用Fibonacci堆( O(| E | + | V | log | V |)),如果不可能,但不推荐意味着使用数组( O(| V | ^ 2 + E))。这应该是根。

- 对于当前节点,您应该更新所有未访问的邻居(未访问,不可用(为什么,见上文))行程成本if((当前节点的成本+连接它们的边缘的权重) ,与邻居)<(从起始节点到达邻居的实际成本))。将不可用更改为可用时,必须将更改的元素添加到优先级队列。当你更新节点的成本时,你应该升级堆,不要忘记。

-Mark实际上是访问过的节点。将他从优先级队列中删除(永久地,访问它),在最小堆中删除它的delete_root操作。

- 重复,直到队列不为空。

在您的示例中,它可能如下所示:

Number - 实际上是节点之间路径的最低总重量(第一个和最后一个)。

星星 - 访问节点,这个成本永远不会改变。

Dash - 节点暂时不可用。

| a | b | c | d |
-----------------
| 0 | - | - | - | <-- Available is only a.
-----------------
|*0*| 1 | 2 | - | <-- You can go to b and c.
-----------------
|*0*|*1*| 2 | 16| <-- b was cheaper, you updated costs from this vertex.
-----------------
|*0*|*1*|*2*| 3 | <-- You didn't stop, and find less costly way!
-----------------
|*0*|*1*|*2*|*3*| <-- Work done, the last vertex visited.
-----------------

更具体地说,最初可用的只是第一个元素,所以在开始时你必须访问他。完成后,可用两个新节点,您应该访问最便宜的(从可用,未访问)。这是b。从b是d的唯一途径,所以你只升级他的成本(现在d是可用的,但实际的方式(成本)可能不是最优的)。再次从可用的最便宜的顶点。这是c,因为a和b被访问,2小于16.当你检查这个节点你找到更好的方法d,所以你应该将d的成本从16更新到3.访问的最后一个节点(d)是正式的,无关紧要的移动。您访问了所有顶点,现在您的工作已经完成。

答案 2 :(得分:0)

每次算法访问节点时,它都会将其所有邻居(尚未访问过的邻居)放入优先级队列。优先级队列使元素按最低成本排序,以便始终首先计算最短距离。

所以为了回答你的问题,它来自a-> b,然后a-> c,然后b-> d,然后c-> d。

答案 3 :(得分:0)

如果你想加速算法,我建议你用二进制堆实现算法。基本上它的作用是它总是通过非常基本的搜索来测试下一个可能的最低成本节点。

http://algorithms.soc.srcf.net/notes/dijkstra_with_heaps.pdf