在Kruskal的算法中使用union-find是否会影响最坏情况的运行时?

时间:2015-08-16 22:53:32

标签: algorithm data-structures time-complexity graph-algorithm

所以我正在教自己一些图形算法,现在在Kruskal上,并且理解建议使用union-find,因此检查添加边创建一个循环是否只需要O(Log V)时间。出于实际目的,我明白你为什么要这么做,但是严格地看一下Big O符号,这样做实际上会影响最坏情况的复杂性吗?

我的理由:如果不是联合查找,我们做了DFS来检查周期,那个运行时间是O(E + V),你必须为O的运行时间执行V次(V ^ 2 + VE)。它不仅仅是union find,也就是O(V * LogV),但Kruskal的大部分复杂性来自于删除优先级队列的最小元素E次,即O(E * logE),大O回答。我没有真正看到空间优势,因为union-find需要O(V)空间,你需要维护的数据结构也需要使用DFS来查找循环。

对于一个简单的问题,这可能是一个过长的解释:在Kruskal的算法中使用union-find是否会影响最坏情况的运行时间?

1 个答案:

答案 0 :(得分:7)

  

并了解建议使用union-find,以便检查添加边创建一个循环是否只需要O(Log V)时间

这是不对的。使用union findO(alpha(n) * m),其中alpha(n)是Ackermann函数的反函数,并且,对于所有意图和目的,可以认为是常数。比对数快得多:

  

由于alpha(n)与此函数相反,alpha(n)对于n的所有远程实用值都小于5。因此,每次操作的摊销运行时间实际上是一个很小的常数。

  

但Kruskal的大部分复杂性来自于删除优先级队列的最小元素E次

这也是错误的。 Kruskal's algorithm不涉及使用任何优先级队列。它涉及在开始时按成本对边缘进行分类。虽然复杂性仍然是你提到的这一步骤。但是,实际排序可能比优先级队列更快(使用优先级队列最多等同于堆排序,这不是最快的排序算法)。

底线,如果m是边数,n是节点数。:

  1. 对边缘进行排序:O(m log m)

  2. 对于每个边缘,请致电union-findO(m * alpha(n)),或基本上只是O(m)

  3. 总复杂度:O(m log m + m * alpha(n))

  4. 如果您不使用union-find,如果我们使用您的O(m log m + m * (n + m))循环查找算法,则总复杂度将为O(n + m)。虽然此步骤的O(n + m)可能是轻描淡写的,因为您还必须以某种方式更新结构(插入边缘)。天真的不相交集算法实际上是O(n log n),所以更糟糕。

  5. 注意:在这种情况下,如果您愿意,可以写log n而不是log m,因为m = O(n^2)log(n^2) = 2log n

    总结:是的,union-find有助于很多

    即使您使用了union-find的O(log n)变体,这会导致O(m log m + m log n)总体复杂度,您可以将其与O(m log m)同化,但在实践中,您宁愿保留如果可以,第二部分会更快。由于union-find很容易实现,所以没有理由不这样做。