Dijkstra和Prim的算法有什么区别?

时间:2012-12-10 04:19:10

标签: algorithm shortest-path

任何人都可以告诉我Dijkstra'sPrim's算法之间的区别吗?我知道每个算法的作用。但他们看起来和我一样。 Dijkstra算法存储最小成本边的总和,而Prim算法存储最多一个最小成本边。这不一样吗?

6 个答案:

答案 0 :(得分:45)

Dijsktra的算法找到从节点i到所有节点的最小距离 (您指定i)。因此,作为回报,您将从节点i获得最小距离树。

Prims算法为您提供给定图表的最小spaning树。连接所有节点的树,而所有成本的总和是最小可能的。

因此,使用Dijkstra 您可以从选定的节点转到任何其他节点,您不会使用Prim的

答案 1 :(得分:28)

我看到的唯一区别是Prim算法存储最小成本边缘,而Dijkstra算法存储从源顶点到当前顶点的总成本。

Dijkstra为您提供了从源节点到目标节点的方式,使成本最低。然而,Prim的算法为您提供了最小的生成树,使得所有节点都连接在一起,总成本最低。

简单来说:

所以,如果你想部署火车连接几个城市,你会使用Prim的算法。但如果你想从一个城市到另一个城市尽可能多地节省时间,你就会使用Dijkstra的算法。

答案 2 :(得分:19)

两者都可以使用完全相同的通用算​​法实现,如下所示:

Inputs:
  G: Graph
  s: Starting vertex (any for Prim, source for Dijkstra)
  f: a function that takes vertices u and v, returns a number

Generic(G, s, f)
    Q = Enqueue all V with key = infinity, parent = null
    s.key = 0
    While Q is not empty
        u = dequeue Q
        For each v in adj(u)
            if v is in Q and v.key > f(u,v)
                v.key = f(u,v)
                v.parent = u

对于Prim,传递f = w(u, v)并为Dijkstra传递f = u.key + w(u, v)

另一个有趣的事情是,Generic上面也可以实现广度优先搜索(BFS),虽然它会过度,因为实际上不需要昂贵的优先级队列。要将通用算法转换为BFS,请传递f = u.key + 1,这与强制执行所有权重相同(即BFS给出从A点到B遍历所需的最小边数)。

<强>直觉

这是考虑上述通用算法的一种好方法:我们从两个桶A和B开始。最初,将所有顶点放在B中,这样桶A就是空的。然后我们将一个顶点从B移动到A.现在查看A中顶点的所有边,这些边穿过B中的顶点。我们使用这些交叉边的一些标准选择一条边并将相应的顶点从B移动到A.重复此过程,直到B为空。

实现这个想法的一种强制方式是维护A中顶点的边缘优先级队列,该顶点跨越到B.显然,如果图形不稀疏,那将会很麻烦。那么问题是我们可以改为保持顶点的优先级队列吗?事实上,我们最终决定从B中选择哪个顶点。

历史背景

有趣的是,这两种算法背后的技术的通用版本在概念上与1930年一样久,即使电子计算机不存在。

故事始于OtakarBorůvka,他需要一个家庭朋友的算法,试图找出如何用最低成本的电线连接摩拉维亚(现在是捷克共和国的一部分)的城市。他于1926年在数学相关期刊上发表了他的算法,因为计算机科学当时并不存在。这引起了VojtěchJarník的注意,他想到了对Borůvka算法的改进,并于1930年发布了它。事实上,他发现了我们现在所知的Prim算法,它在1957年重新发现它。

独立于所有这些,在1956年,Dijkstra需要编写一个程序来展示他所研究所开发的新计算机的功能。他认为让电脑找到在荷兰两个城市之间旅行的连接会很酷。他在20分钟内设计了算法。他创建了一个64个城市的图表,其中有一些简化(因为他的计算机是6位),并为这台1956年的计算机编写了代码。然而他没有发表他的算法,因为主要是没有计算机科学期刊,他认为这可能不是很重要。第二年,他了解了连接新计算机终端的问题,使得电线长度最小化。他想到了这个问题并重新发现了Jarník/ Prim的算法,该算法再次使用了与他前一年发现的最短路径算法相同的技术。他mentioned他的两种算法都是在不使用笔或纸的情况下设计的。 1959年,他用paper发布了两个算法,长度只有2.5页。

答案 3 :(得分:2)

Dijkstra算法是节点i和j之间的单源最短路径问题,但Prim算法是最小生成树问题。这些算法使用名为“贪婪算法”的编程概念

如果您查看这些概念,请访问

  1. 贪心算法讲义:http://jeffe.cs.illinois.edu/teaching/algorithms/notes/07-greedy.pdf
  2. 最小生成树:http://jeffe.cs.illinois.edu/teaching/algorithms/notes/20-mst.pdf
  3. 单一来源最短路径:http://jeffe.cs.illinois.edu/teaching/algorithms/notes/21-sssp.pdf

答案 4 :(得分:1)

I was bothered with the same question lately, and I think I might share my understanding...

I think the key difference between these two algorithms (Dijkstra and Prim) roots in the problem they are designed to solve, namely, shortest path between two nodes and minimal spanning tree (MST). The formal is to find the shortest path between say, node s and t, and a rational requirement is to visit each edge of the graph at most once. However, it does NOT require us to visit all the node. The latter (MST) is to get us visit ALL the node (at most once), and with the same rational requirement of visiting each edge at most once too.

That being said, Dijkstra allows us to "take shortcut" so long I can get from s to t, without worrying the consequence - once I get to t, I am done! Although there is also a path from s to t in the MST, but this s-t path is created with considerations of all the rest nodes, therefore, this path can be longer than the s-t path found by the Dijstra's algorithm. Below is a quick example with 3 nodes:

                                  2       2  
                          (s) o ----- o ----- o (t)     
                              |               |
                              -----------------
                                      3

Let's say each of the top edges has the cost of 2, and the bottom edge has cost of 3, then Dijktra will tell us to the take the bottom path, since we don't care about the middle node. On the other hand, Prim will return us a MST with the top 2 edges, discarding the bottom edge.

Such difference is also reflected from the subtle difference in the implementations: in Dijkstra's algorithm, one needs to have a book keeping step (for every node) to update the shortest path from s, after absorbing a new node, whereas in Prim's algorithm, there is no such need.

答案 5 :(得分:0)

最简单的解释是在Prims中您未指定起始节点,但是在dijsktra中,您(需要一个起始节点)必须找到从给定节点到所有其他节点的最短路径