我已阅读以下内容,但请查看下面的代码。
Why Dijkstra's Algorithm uses heap (priority queue)?
我有两个版本的dijkstra,一个带有PQueue的好版本,一个带有常规链表列表的坏版本。
document.addEventListener('click', function xyz(e){
e.preventDefault();
//alert(e);
var target = e.target || event.srcElement;
var attributes = Array.prototype.slice.call(target.attributes).map(function(i) {
return [String(i.name)+": "+String(i.value)]
})
alert(attributes);
prompt("xpath1 :",getPathTo(target));
chrome.runtime.sendMessage({method:"captureElement",data:attributes});
},true)
我还使用如下文本文件创建图表
public static void computeDijkstra(Vertex source) {
source.minDistance = 0.;
Queue<Vertex> vertexQueue = new PriorityQueue<Vertex>();
// Queue<Vertex> vertexQueue = new LinkedList<Vertex>();
vertexQueue.add(source);
while (!vertexQueue.isEmpty()) {
Vertex fromVertex = vertexQueue.poll();
if (fromVertex.neighbors != null) {
for (Edge currentEdge : fromVertex.neighbors) {
Vertex toVertex = currentEdge.target;
if (currentEdge.weight + fromVertex.minDistance < toVertex.minDistance) {
toVertex.minDistance = currentEdge.weight + fromVertex.minDistance;
toVertex.previous = fromVertex;
vertexQueue.add(toVertex);
}
}
}
}
}
public static void computeDijkstraBad(Vertex source) {
source.minDistance = 0.;
// Queue<Vertex> vertexQueue = new PriorityQueue<Vertex>();
Queue<Vertex> vertexQueue = new LinkedList<Vertex>();
vertexQueue.add(source);
while (!vertexQueue.isEmpty()) {
Vertex fromVertex = vertexQueue.poll();
if (fromVertex.neighbors != null) {
for (Edge currentEdge : fromVertex.neighbors) {
Vertex toVertex = currentEdge.target;
if (currentEdge.weight + fromVertex.minDistance < toVertex.minDistance) {
toVertex.minDistance = currentEdge.weight + fromVertex.minDistance;
toVertex.previous = fromVertex;
vertexQueue.add(toVertex);
}
}
}
}
}
这两个实现都会呈现以下0, 1, 2, 3, 4, 5, 6 // vertices
0, 6 // from and to vertex
1, (2-5, 0-4, 4-6) // from vertex 1 it will have edge to 2 with weight 5 ...
0, (4-3, 3-7)
4, (2-11, 3-8)
3, (2-2, 5-5)
2, (6-2, 5-10)
5, (6-3)
,这是从0到6的最短路径!
现在我们知道,如果使用简单BFS来找到具有正整数的最短距离,则会出现无法找到最小路径的情况。所以,有人可以给我一个反例,我的Bad实现将无法为图形打印正确的路径。请随意以我使用的图表格式(示例文本文件格式)给出答案。
到目前为止,我所有的图表,两个实现都得到了正确的结果。这不应该发生,因为糟糕的实现是运行时(E + V),我们知道我们找不到至少E log V的最短路径。
另一个例子,
[0, 3, 2, 6]
两种实现都呈现[0,3,5,6,8,10],这是从0到10的正确最短路径。
答案 0 :(得分:3)
我相信你给出的算法是正确的,但它没有Dijkstra算法那么有效。
在较高级别,您的算法通过查找“活动”节点(距离已降低的节点),然后扫描输出边缘以激活需要更新距离的所有相邻节点来工作。请注意,同一节点可以多次激活 - 事实上,每次候选距离下降时,节点可能会被激活一次,这可能会在算法运行中多次发生。此外,如果候选距离下降多次,您实施的算法可能会多次将同一节点放入队列,因此除了第一个之外的所有队列都可能是不必要的。总的来说,我认为这会导致大型图形的运行时间大幅增加。
从某种意义上说,你实现的算法是最短路径算法,但它不是Dijkstra的算法。主要的区别在于Dijkstra的算法使用优先级队列来确保每个节点出列一次并且只处理一次,从而提高效率。
所以我想我能给出的最佳答案是“你的算法不是Dijkstra算法的实现,而Dijkstra算法使用优先级队列的原因是避免以算法的方式多次重新计算距离。”
答案 1 :(得分:2)
您的算法将找到正确的结果,但您的方法正在做的是它会降低Dijkstra方法的效率。
示例:
考虑名为A B C的3个节点。
A->C :7
A->B :2
B->C :3
在你糟糕的方法中,你首先将从A到C的最短路径设置为7,然后,当你遍历时,你将它修改为5(A-> B-C)
在Dijkstra的方法中,根本不会遍历A-> C,因为当使用最小堆时,首先遍历A-> B,B将被标记为“遍历”,然后B- &gt;将遍历C,并且C将被标记为“遍历”。 现在,由于C已被标记为“遍历”,因此将永远不会检查路径A-> C(长度为7)。
因此,正如您所看到的,在您糟糕的方法中,您将达到C 2次(A-> C&amp; A-> B-> C),而使用Dijkstra的方法,您将去C只有一次。
这个例子应该证明你使用Dijkstra算法的迭代次数会减少。
答案 2 :(得分:0)
阅读其他人的答案,他们是正确的,并且总结是错误的实施方法是正确的,但是所有者主张的复杂度(O(E + V))是不正确的。没人提及的另一件事,我将在这里添加。
这种糟糕的实现方式也对应于一种算法,该算法实际上是BFS的派生形式,正式名称为 SPFA 。签出SPFA algorithm。当作者于1994年发布此算法时,他声称它的性能优于Dijkstra(具有O(E)复杂度),这是错误的。
它在ACM学生中非常受欢迎。由于其简单性和易于实施。至于性能,Dijkstra是首选。
对this post的类似回复