如何使用堆来优化Prim的最小生成树算法?

时间:2014-12-29 19:23:25

标签: algorithm graph-theory minimum-spanning-tree

我必须解决一个类似这样的问题:
我得到一个数字N代表我的分数。每个点都有两个坐标: X和Y。

我可以通过以下公式找到两点之间的距离:
ABS(X2-X1)+ ABS(Y2-Y1)下,
(x1,y1)是第一点的坐标,(x2,y2)是第二点的坐标,abs()是绝对值。

我必须找到最小生成树,这意味着我必须将所有点连接起来,边缘之和最小。 Prim的算法很好,但它太慢了。我读到我可以使用heap加快速度,但我找不到任何解释如何操作的文章。

任何人都可以向我解释Prim的算法如何与堆一起工作(一些示例代码会很好但不是必需的),拜托?

3 个答案:

答案 0 :(得分:1)

有效地解决这个问题(在O(n log n)时间内),但并不容易。只是将Prim的算法与堆一起使用并没有帮助(它实际上使它更慢),因为它的时间复杂度为O(E log V),在这种情况下为O(n^2 * log n)

但是,您可以使用Delaunay三角剖分来减少图中的边数。 Delaunay三角剖分图是平面的,因此它具有线性边数。这就是为什么运行带有堆的Prim算法会导致O(n log n)时间复杂度(O(n)个边和n个顶点)。你可以在这里阅读更多相关内容(详细介绍这个算法并证明其正确性会使我的回答太长):http://en.wikipedia.org/wiki/Euclidean_minimum_spanning_tree。请注意,即使文章是关于欧几里得mst,你的情况的方法基本相同(也可以有效地建立曼哈顿距离的Delaunay三角剖分。)

Prim的算法与堆本身的描述已经存在于你的问题的另外两个答案中。

答案 1 :(得分:0)

来自Prim's algorithm上的维基百科文章:

  

[S]转动顶点而不是边缘可以进一步改善它。堆应该按最小边权重对顶点进行排序,将它们连接到部分构造的最小生成树(MST)中的任何顶点(如果不存在这样的边,则为无穷大)。每次选择顶点 v 并将其添加到MST时,对部分MST外的所有顶点 w 执行减少键操作,使得v连接到w,将密钥设置为其先前值的最小值和(v,w)的边缘成本

答案 2 :(得分:0)

虽然有人指出带堆的Prim's是O(E log V),在最坏的情况下为O(n ^ 2 log n),但我可以提供在最坏的情况下使堆更快的原因情况,因为尚未得到答复。

使Prim在O(V ^ 2)如此昂贵的原因是必须更新算法中的每个迭代。通常,Prim的工作方式是保留一张与其他顶点长度最小的顶点表,并选择最便宜的顶点添加到您的生长树中,直到全部添加为止。每次添加顶点时,都必须返回到表并更新现在可以以较小权重访问的所有顶点。然后,您必须一直走到表格的最前面,以确定添加最便宜的顶点。这种设置-必须选择下一个顶点(O(V))V次-得出O(V ^ 2)。

除了最坏的情况之外,堆都能帮助此运行时间,因为它可以解决此瓶颈。通过使用最小堆,可以访问O(1)中考虑的最小重量。此外,在向其添加一个数字以维护其属性后,修复该堆需要花费O(log V),这对于O(E log V)进行E次以维护Prim's的堆来说要花费E倍。这成为新的瓶颈,这导致了O(E log V)的最终运行时间。

因此,根据您对数据的了解程度,带有堆的Prim's肯定比没有堆的效率更高!