一,算法分析
Prim算法简述
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:V new= {x},其中x为集合V中的任一节点(起始点),E new= {},为空;
3).重复下列操作,直到V new= V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合V new中的元素,而v不在V new集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合V new中,将<u, v>边加入集合E new中;
4).输出:使用集合V new和E new来描述所得到的最小生成树。
二,代码
#include<iostream>
#define MAX 1000000
using namespace std;
int main(){
int min = MAX;
int points =6;
int edges = 10;
int edge[points][points];
int dis=0;//最短距离数组
int flag[points]={0};//是否经过数组
//初始化数组
for(int i = 0;i<points;i++){
for(int j = 0;j<points;j++){
edge[i][j]=MAX;
}
}
cout<<"请输入位置距离关系:"<<endl;
int p1,p2,w;
for(int i=0;i<edges;i++){
cin>>p1>>p2>>w;
edge[p1][p2]=w;
edge[p2][p1]=w;
}
flag[0]=1;
for(int count=0; count<points-1;count++){//points-1次对点搜索
int min_i = 0;
int min_k = 0;
for(int k = 0;k<points;k++){//对所有在visited最短距离数组中才进行查找最短距离
if(flag[k]==1){
//如果属于最短距离数组
for(int i = 0;i<points;i++){//对在最短距离数组里的每一个点查找最短距离
if(min>edge[k][i]&&flag[i]==0){
min = edge[k][i];
min_k = k;
min_i = i;
}
}
}
}
flag[min_i] = 1;
dis +=min;
cout<<min_k<<"--"<<min_i<<endl;
edge[min_k][min_i]=MAX;
edge[min_i][min_k]=MAX;
min = MAX;//每次查找完,将min恢复为MAX
}
cout<<"最短距离:"<<dis;
}
三,算法效率
Prim算法分析:
使用邻接矩阵来保存图的话,时间复杂度是O(V^2)。
在每一遍V-1次迭代中,都要遍历实现优先队列的数组,来查找并删除距离最小的顶点,如果有必要再更新余下顶点的优先级。
如果图是用邻接链表表示的,并且优先队列是由最小堆实现的,该算法的运行时间属于
O
(
∣
E
∣
l
o
g
∣
V
∣
)
O(|E|log|V|)
O(∣E∣log∣V∣).因为该算法执行了|V|-1次删除最小元素的操作,并且进行了|E|次验证,如有必要,还要对一个规模不大于|V|的最小堆改变其元素的优先级,运行时间属于
(
∣
V
∣
−
1
+
∣
E
∣
)
O
(
l
o
g
∣
V
∣
)
=
O
(
∣
E
∣
l
o
g
∣
V
∣
)
(|V|-1+|E|)O(log|V|) = O(|E|log|V|)
(∣V∣−1+∣E∣)O(log∣V∣)=O(∣E∣log∣V∣)