答案-1
第一个问题可以在 stackoverflow from- this question中找到。
答案-2
提取最小操作在 O(1) 时间内从根中获取最小元素,但与此同时,我们需要执行使下一个提取最小操作在 O(1) 时间内提供最小元素的操作。我们做什么?我们只是将根元素与最右边的叶节点交换,然后删除该叶节点并堆积根,这可能会向下渗透到叶节点,这意味着 O(logn) 复杂度。(如 2^h=n 然后 h=log2(n))。
答案-3
对于无向图
现在为什么是2E。好的!每个节点都有一些连接到它的边缘。(如果没有连接,那么它的度数为零)。现在节点的度数为 n 意味着它有 n 条边连接到它。现在让我们举个例子
1---2
| /
| /
3
1 has degree=2
2 has degree=2
3 has degree=2
-+-+-+-+-+-+-+-
so sum(deg(v))=2+2+2=6= 2*(no of edges);
为什么这样?您可以考虑将这种情况建模为握手 b/2 朋友。每个节点表示朋友,每条边表示握手。如果你和 B 握手,那么 B 也会和你握手。所以每个握手(边缘)被节点(朋友)考虑两次。
注意:对于有向图,结果将等于E
答案-4
这些链接已经解释了它。检查这个希望一切都会清楚
1.链接1
2.链接2
让我们在这里说清楚。算法是什么——在 cormen 中是这样给出的——
MST-PRIM(G, w, r)
1 for each u ∈ V [G] ~~~~~~~~~> O(V)
2 do key[u] ← ∞
3 π[u] ← NIL
4 key[r] ← 0
5 Q ← V [G] ~~~~~~~~~> If binary min-heap used then heapification's comlexity is O(V)
6 while Q ≠ Ø ~~~~~~~~~> Executed |V| times
7 do u ← EXTRACT-MIN(Q)~~~> O(logV) in binary heap
8 for each v ∈ Adj[u] ~~~> For each vertex the degree of that vertex times it will loop. So total O(E) times
9 do if v ∈ Q and w(u, v) < key[v]
10 then π[v] ← u
11 key[v] ← w(u, v)~~~> decrease key operation in min-heap(binary) O(logV) times.
所以总复杂度= O(V)+O(VlogV)+O(ElogV) = O((V+E)logV) //VlogV支配V
现在,如果所有边缘权重都在 1 到 |V| 的范围内 那么我们可以只取一个列表数组 A[1..|V|]。现在假设边权重为 1(E1)、3(E2)、2(E3)、5(E4)、7(E5)、3(E6),并且有 7 个顶点和 6 个边。
最初的列表数组
A [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
0 1 2 3 4 5 6 7
现在您应用计数排序的方法 - 对于每个边缘权重,您将该边缘放在相应的数组位置,例如
现在遇到边缘 E1 后,数组将是
A [ ] [E1] [ ] [ ] [ ] [ ] [ ] [ ]
0 1 2 3 4 5 6 7
然后是边缘 E2
A [ ] [E1] [ ] [E2] [ ] [ ] [ ] [ ]
0 1 2 3 4 5 6 7
所以在遍历所有边之后你得到
E6
|
A [ ] [E1] [E3] [E2] [ ] [E4] [ ] [E5]
0 1 2 3 4 5 6 7
可能现在您可以理解为什么提到|V|的某些答案了 列出或 |W| 此图中的列表。
现在你可以在 O(V) 时间内从数组中得到所有最小值。通常对于大范围的权重,堆数据结构用于存储边。
但是,在这种情况下,权重是 1 .. |V| 所以你可以简单地将边缘存储在|V|中 单独的列表,一个用于权重为 1 到 |V| 的边。
要找到权重最低的边,只需从第一个列表中取一个,除非它是空的,在这种情况下,您从第二个列表中取一个边。
从列表中访问和删除元素是 O(1),您只需从列表中删除最上面的元素。所以 Prim 的算法将以 O(V*W+E) 运行。
所以如果 W=O(V) 那么它运行在 O(V^2+E)
如果权重在 1..W 范围内(W=O(1) 常数),那么复杂度同样将是 O(V*W+E)。〜O(V + E)。
伪代码
在 C 中
结构边缘 { int u,v,w; } 结构列表节点 { 边 e; 结构列表节点*下一个;}
struct listnode ** A;
A=malloc(sizeof(struct list *)*N);
Intilally all of A[i]=NULL;
A[i]=malloc(sizeof(struct listnode),1);
(*A[i]).e.u=..
(*A[i]).e.v=..
(*A[i]).e.w=..
create the array of lists don't insert anythiing.
Then just select a vertex say s
keep an array visisted[1..|V|]
visited[s]=true;
no_of_visited=1;
recently_visted=s;
while(all nodes are not visited) //no_of_visited!=|V|
{
insert all edges from s-x (adjacent) in the array of lists.(s is recently visited) provided x is not visited
get the minimum weight one
if it is u-w and w is not visited
{
visited[w]=true;
no_of_visited++;
recently_visited=w;
insert(u,w) in spanning tree
}
}
复杂性分析
算法:
让我们的权重在 1..|W| 范围内
Then just select a vertex say s ~~~~~~~~~~> O(1)
//keep an array visisted[1..|W|]
for i=1 to |W|
visited[i]=false; ~~~~~~~~~~> O(|W|)
visited[s]=true; ~~~~~~~~~~> O(1)
no_of_visited=1; ~~~~~~~~~~> O(1)
recently_visted=s; ~~~~~~~~~~~ O(1)
while(all nodes are not visited) ~~~~~O(V) //no_of_visited!=|W|
{
insert all edges from s-x (adjacent) in the array of lists.(s is recently visited) provided x is not visited ~~~~~O(|E|) altogether
get the minimum weight one ~~~~~O(|W|)
if it is u-w and w is not visited --O(1)
{
visited[w]=true;
no_of_visited++;
recently_visited=w;
insert(u,w) in spanning tree --O(1)
}
}
所以复杂度=O(|W|)+O(|W|.|V|)+O(|E|)~O(E+V W) 当W=O(V)时T(V,E)= O(E+VV )=O(E+V^2)