【问题标题】:Kruskal with Heap or Sort Algorithm使用堆或排序算法的 Kruskal
【发布时间】:2015-11-08 07:08:09
【问题描述】:

我正在尝试尽可能高效地实施 Kruskal。

为了运行时效率,使用堆或排序算法对边进行排序有区别吗?

还有哪些其他技术可以让 Kruskal 算法更有效地工作?

【问题讨论】:

  • 这是只有一个正确答案的问题之一:使用您自己的数据对所有选项进行基准测试,没有通用答案。使用堆可能对某些图的平均情况有优势,但堆在缓存方面非常糟糕。如果你想“尽可能高效”,我假设你不希望缓存未命中减慢你的代码。

标签: java algorithm time graph-theory kruskals-algorithm


【解决方案1】:

这取决于您要解决的确切问题。如果您正在实施通用解决方案,只需选择“最快”的排序算法。我怀疑那是堆排序。我只会使用默认情况下Java使用的任何排序算法(可能是timsort,如果你正在排序对象)。此外,在某些情况下,排序可以比O(ElogE) 更快地完成。假设你的边只能有一个小的间隔内的整数权重,那么也许你可以选择与计数排序非常相似的东西。因此,如果您处于其中一种情况,那么堆可能不是一个好的选择。 另外,我看不出有人会单独在 Kruskal 算法的上下文中使用堆的任何理由。

要回答您的第二个问题(但您可能已经知道这一点),使用 Disjoint-set data structure 对集合进行操作可以提高速度。它具有各种优点:易于实现、良好的渐近行为和低常数。

编辑

我重新考虑了 heap/heapsort 选项,主要是由于我帖子中的 cmets。如果只在树完成之前进行排序,使用堆可能确实会带来巨大的优势。 180 度打开我的观点。这就是原因。

考虑Erdős–Rényi model。现在,这是一个非常简单的模型,其中从n 顶点(即无边)上的空图G 开始,并将每个可能的边以概率p 添加到G,独立于任何其他边。这并不完全是 Kruskal 算法在组成树时所做的,但如果 G 具有二次边数(就顶点数而言),边分布不是“有偏差的”并且权重分配不是“有偏见的”。

现在有趣的部分来了。在 Erdős–Rényi 模型下,当p 近似于ln(n)/n(即“粗略地”说,在向图中添加O(nln(n)) 边之后)时,图变得连通。结果众所周知有一段时间了(检查here)。

虽然 Kruskal 算法的设置不同,但如果 G 具有二次边数(就顶点数而言),则边分布不是“有偏差的”,权重分配也不是“有偏见的',在O(nln(n)) 边缘内可以到达一棵树是合理的。如果这确实是真的,那么使用堆并仅在树完成之前进行排序比在开始组合树之前使用比较排序方法对整个边集进行排序要好。

因此,使用堆可能还会提高运行时速度,而且可能相当可观。

【讨论】:

  • 我认为使用堆的主要好处是能够进行部分排序,只排序直到树完成。如果在您的数据集中,树通常可以在 O(V) 边缘内到达,那么使用堆可以加快速度。但是,同样,堆有一个非常高的常数,所以速度必须相当大才能让它值得。
  • 再想一想,另一个好处是堆排序的最坏情况复杂性更好。对于具有严格时间限制的实时系统,能够确定性地预测算法需要多长时间(无论输入如何)是一个优势。
  • 我用堆和排序算法实现了 Kruskal,事实上,堆对于这些实例来说更快。但是今天我再次测试它,现在它们的速度相同。我真的无法理解。
  • 我做了更多的研究并遇到了这个dcc.uchile.cl/~gnavarro/ps/algor09.pdf
最近更新 更多