Answer-1
The first question can be found in stackoverflow from- this question.
Answer-2
Extract min operation gets the minimum element from root in O(1) time but along with that we need to perform operations that will make the next Extract min operation to give min element in O(1) time. What do we do? We just swap the root element with the rightmost leaf node and then delete that leaf node and heapify the root which may percolate down the new root to leaf node and that mean O(logn) complexity. (as 2^h=n then h=log2(n)).
Answer-3
For undirected graph
Now why 2E. okay! each node has some edge connected to it.(if not connected then it's degree is zero). Now node has degree n means it has n edges connected to it. Now let's take an example
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);
Why so? You can consider model this situation as an handshake b/2 friends. Each node denotes friends and each edge denotes handshake. If you shook hand with B then B will handshake with you also. So each handshake(edge) is considered twice by the nodes(friends).
Note: For directed graph the result will be equal to E
Answer-4
These links already explain it. Check this hope everything will be clear
1.link1
2.link2
let's be clear over here. What is the algorithm-In cormen it is given this way-
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.
So total comlexity= O(V)+O(VlogV)+O(ElogV)
= O((V+E)logV) //VlogV dominates V
Now if all the edge weights are in range 1 to |V| then we can just take an array of lists A[1..|V|]. Now let's say edge weights are 1(E1),3(E2),2(E3),5(E4),7(E5), 3(E6)and there 7 vertices and 6 edges.
Array of lists initially
A [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
0 1 2 3 4 5 6 7
Now you apply the method of counting sort- for each edge weight you put that edge in corresponding array location like
Now after encounterng the edge E1 the array will be
A [ ] [E1] [ ] [ ] [ ] [ ] [ ] [ ]
0 1 2 3 4 5 6 7
then after that for edge E2
A [ ] [E1] [ ] [E2] [ ] [ ] [ ] [ ]
0 1 2 3 4 5 6 7
So after traversing all edges you get
E6
|
A [ ] [E1] [E3] [E2] [ ] [E4] [ ] [E5]
0 1 2 3 4 5 6 7
Probably now you can understand why did some answer mentioned of |V| lists or |W| lists from this diagram.
Now what you can get all the minimums from the array in O(V) time.
Normally for wide range of weights heap data structure is used to store the edges.
However, in this case, the weights are either 1 .. |V| and so you can simply store the edges in |V| separate lists, one for edges with weight 1 to |V|.
To find the edge with lowest weight you simply take one from the first list, unless it is empty, in which case you take an edge from the second list.
Accessing and deleting an element from a list is O(1) and you just delete the topmost element from the list. so Prim's algorithm will run in O(V*W+E).
So if W=O(V) then it runs in O(V^2+E)
If the weights are in range 1..W (W=O(1) constant) then complexity similarly will be O(V*W+E).
~O(V+E).
The pseudocode
In C
struct edge
{
int u,v,w;
}
struct listnode
{
edge e;
struct listnode *next;
}
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
}
}
Complexity Analysis
Algo:
Let's the weights are in the range 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)
}
}
So complexity=O(|W|)+O(|W|.|V|)+O(|E|)~O(E+VW)
When W=O(V) then T(V,E)= O(E+VV)=O(E+V^2)