假设图中的所有边权重都是从1到| V |的整数。你能以多快的速度运行Prim的算法?如果边缘权重是1到W范围内的整数,对于某个常数W?
,该怎么办?我认为,由于Prim算法基于min-heap的实现,因此有关边缘权重的知识无助于加快过程。这是对的吗?
答案 0 :(得分:0)
使用此约束,您可以实现分别使用O(V)
/ O(W)
空格但具有O(1)
insert和O(1)
extract-min操作的堆。实际上,对于Prim算法所需的所有操作,您都可以获得O(1)
。由于堆的时间复杂性会影响主算法的复杂性,因此您可以比默认的通用实现更好。
答案 1 :(得分:0)
我认为解决这个问题的主要想法是记住 W 是一个常量,所以,如果你把你的优先级队列表示为一个大小受 W ,在每次迭代时遍历整个列表不会改变算法的时间复杂度......
例如,如果您将优先级队列表示为具有 W + 1 位置的数组 T ,则在每个位置都有一个顶点的链接列表,以便 T [i] 是一个列表,其中所有顶点的优先级等于 i ,并使用 T [W + 1] 来存储优先级等于的顶点无限,你会采取
O(V)构建优先级队列(只需在列表中插入所有顶点 T [W + 1] )
O(W)到提取最小元素(只是旅行 T 搜索非空的第一个位置)
O(1)减少键(如果顶点 v 键等于 i ,则更新为 j < / strong>,从列表 T [i] 中取出 v 并插入列表的第一个位置 T [j] )
因此,它会给你复杂性 O(VW + E)而不是 O(V logV + E)。
(当然,如果范围从1到 V ,它将无效,因为 V ^ 2 + E 大于 V \ logV + ë强>)。
答案 2 :(得分:0)
对于非二进制堆Prim的实现,伪代码可以在Cormen(算法简介)第三版中找到。
知道范围是1 ... k,我们可以创建一个大小为k的数组,并遍历列表,为相应的权重添加边。就其存储性质而言,这意味着边缘按权重排序。这将是O(n + m)时间。
依靠Cormen中Prim算法的伪代码,我们可以分析其复杂度以得出O(nlog {n} + mlog {n})= O((n + m)log {n})时间(Cormen页面) 636)。具体而言,步骤7和步骤11贡献了在n和m循环上迭代的log {n}元素。 n log {n}循环来自EXTRACT-MIN操作,m log {n}循环来自“隐式DECREASE-KEY”操作。两者都可以用我们的边缘权重数组(O(k)的循环)代替。因此,使用改良的Prim's算法,我们将获得O(nk + mk)= O(k(n + m))算法。