O(V2)
?O(V2)
?Adjacency Matrix
A B C D E
--------------
A 0 1 0 3 2
B 1 0 0 0 2
C 0 0 0 4 3
D 3 0 4 0 1
E 2 2 3 1 0
普里姆算法是一种算法,它接受一个图和一个起始节点,并在该图上找到最小生成树 - 即找到一个子集,使结果为包含所有节点且组合边权值最小的树。可以概括如下:
我们现在可以开始分析算法:
然而,jozefg给出了一个好答案,展示了如何实现O(V ^ 2)的复杂度。
Distance to Tree
| A B C D E
|----------------
Iteration 0 | 0 1* # 3 2
1 | 0 0 # 3 2*
2 | 0 0 4 1* 0
3 | 0 0 3* 0 0
4 | 0 0 0 0 0
NB. # = infinity (not connected to tree)
* = minimum weight edge in this iteration
这里的距离向量表示连接每个节点到树的最小加权边,并用于以下操作:
使用这三个步骤将搜索时间从O(E)降低到O(V),并在每次迭代中添加额外的O(V)步骤来更新distance向量。由于每次迭代现在都是O(V),因此总复杂度为O(V^2)。
传统的Prim算法实现方式是使用一个数组来存储除邻接矩阵外的信息,我们称之为distance
,它表示该顶点到节点的最小距离。这样,我们只需检查distance
以找到下一个目标,由于我们需要执行V次操作,而distance
有V个元素,因此我们的时间复杂度为O(V^2)
。
仅凭这些还不够,因为distance
中的原始值很快就会变得过时。为了更新这个数组,我们只需在每一步结束时遍历邻接矩阵并适当地更新distance
即可。这不会影响我们的时间复杂度,因为这仅意味着每一步需要O(V+V) = O(2V) = O(V)
的时间。因此,我们的算法是O(V^2)
。
如果不使用distance
,则每次都必须遍历所有E个边,最坏情况下包含V^2条边,这意味着我们的时间复杂度将是O(V^3)
。
证明:
为了证明没有distance
数组时不可能在O(V^2)
的时间内计算MST,考虑到在大小为n
的树上的每次迭代中,有V-n
个顶点可能会被添加。
要计算应选择哪一个,我们必须检查它们中的每一个以找到它们与树的最小距离,然后将其与其他节点进行比较并找到最小值。
在最坏的情况下,每个节点都包含到树中每个节点的连接,导致有n * (V-n)条边,时间复杂度为O(n(V-n))
。
由于我们的总和是每个步骤的总和,而n从1变化到V,因此我们的最终时间复杂度为:
(sum O(n(V-n)) as n = 1 to V) = O(1/6(V-1) V (V+1)) = O(V^3)
QED
首先,显然至少是O(V^2),因为邻接矩阵的大小就是这么大。
看一下http://en.wikipedia.org/wiki/Prim%27s_algorithm,你需要执行“重复直到Vnew = V” V次的步骤。
在这个步骤中,你需要计算出V中任何一个顶点和V外任何一个顶点之间的最短链接。维护一个大小为V的数组,对于每个顶点,要么是无穷大(如果该顶点在V中),要么是任何一个顶点与该顶点之间的最短链接及其长度(因此在开始时,这仅来自起始顶点与每个其他顶点之间的链接长度)。要找到要添加到V中的下一个顶点,只需搜索这个数组,成本为V。一旦你有了一个新的顶点,就查看从该顶点到每个其他顶点的所有链接,并查看它们是否提供了从V到该顶点的更短链接。如果是,更新数组。这也需要成本V。
因此,你有V个步骤(V个顶点要添加),每个步骤花费V,这给出O(V^2)。