你知道的最快的Dijkstra实现是什么(在C ++中)?

时间:2009-06-02 07:37:44

标签: c++ performance algorithm

我最近将Dijkstra算法的第3版附加到我的项目中,以获得单一来源的最短路径。

我意识到有许多不同的实现方式在性能上有很大差异,并且在大图中的结果质量也有所不同。使用我的数据集(> 100,000个顶点),运行时间从20分钟到几秒不等。最短路径也变化1-2%。

您知道哪种最佳实施方式?

修改 我的数据是一个液压网络,每个节点有1到5个顶点。它可以与街道地图相媲美。我对已经加速的算法做了一些修改(使用所有剩余节点的排序列表),现在在一小部分时间内找到相同的结果。我已经搜索了这样的事情了很长一段时间。我想知道这样的实现是否已经存在。

我无法解释结果的细微差别。我知道Dijkstra不是启发式的,但所有的实现似乎都是正确的。更快的解决方案具有更短路径的结果。我只使用双精度数学。

编辑2: 我发现找到的路径的差异确实是我的错。我已经为某些顶点插入了特殊处理(仅在一个方向上有效),并在其他实现中忘记了这一点。

但是我仍然感到惊讶的是Dijkstra可以通过以下变化大幅加速: 通常,Dijkstra算法包含如下循环:

MyListType toDoList; // List sorted by smallest distance 
InsertAllNodes(toDoList);
while(! toDoList.empty())
{
    MyNodeType *node = *toDoList.first();
    toDoList.erase(toDoList.first());
    ...
}

如果你稍微改变一下,它的效果相同,但表现更好:

MyListType toDoList; // List sorted by smallest distance 
toDoList.insert(startNode);
while(! toDoList.empty())
{
    MyNodeType *node = *toDoList.first();
    toDoList.erase(toDoList.first());
    for(MyNeigborType *x = node.Neigbors; x != NULL; x++)
    {
        ...
        toDoList.insert(x->Node);
    }
}

看起来,这种修改通过一个数量级而不是指数的顺序减少了运行时间。它将我的运行时形式从30秒减少到小于2.我在任何文献中都找不到这种修改。同样非常清楚的是,原因在于排序列表。插入/擦除功能要差得多,只需要一只手就可以使用100.000元素。

解答:

经过大量的谷歌搜索后,我发现了自己。答案很清楚: 的 boost graph lib 即可。太棒了 - 我有一段时间没有找到这个。如果您认为Dijkstra实施之间没有性能差异,请参阅wikipedia

5 个答案:

答案 0 :(得分:11)

道路网络已知的最佳实施方案(> 100万个节点)的查询时间以秒表示。有关第9次DIMACS实施挑战(2006)的详细信息,请参阅。请注意,这些不仅仅是Dijkstra,当然,因为重点是让结果更快。

答案 1 :(得分:3)

可能我没有回答你的问题。我的观点是,当你的问题有更高效的算法时,为什么要使用Dijkstra。如果你的图形填满了三角形属性(它是一个欧几里德图)

| AB | + | BC | > | AC |

(从节点a到节点b的距离加上从节点b到节点c的距离大于从节点a到节点c的距离)然后您可以应用A *算法。 该算法非常有效。否则考虑使用启发式。 实施不是主要问题。要使用的算法很重要。

答案 2 :(得分:2)

我想做两点: 1)Dijkstra vs A * Dijkstra的算法是动态编程算法,而不是启发式算法。 A *是一种启发式方法,因为它还使用启发式函数(比方说h(x))来估算"点x到达终点的距离有多近。此信息将在后续探索下一个节点的决策中使用。

对于诸如欧几里德图之类的情况,A *运行良好,因为启发函数很容易定义(例如,可以简单地使用欧几里德距离)。但是,对于非欧几里德图,定义启发式函数可能更难,错误的定义可能导致非最优路径。

因此,dijkstra优于A *,它适用于任何一般图形(除了A *在某些情况下更快)。很可能某些实现可以互换地使用这些算法,从而产生不同的结果。

2)dijkstra算法(以及其他诸如A *)使用优先级队列来获取要探索的下一个节点。一个好的实现可能使用堆而不是队列,更好的实现可能使用fibonacci堆。这可以解释不同的运行时间。

答案 3 :(得分:1)

我最后一次检查时,Dijkstra的算法会返回一个最佳解决方案。 Dijkstra的所有“真实”实现每次都应返回相同的结果。

类似地,渐近分析向我们表明,随着输入大小的增加,对特定实现的次要优化不会显着影响性能。

答案 4 :(得分:0)

这将取决于很多事情。您对输入数据了解多少?它是密集的还是稀疏的?这将改变算法的哪个版本最快。

如果它很密集,只需使用矩阵。如果它稀疏,您可能希望查看更有效的数据结构以查找下一个最近的顶点。如果您有关于数据集的更多信息而不仅仅是图形连接,那么请查看其他算法是否能像A *一样更好地工作。

问题是,没有“最快”的算法版本。