- 普里姆算法其实就是结点优先算法,从图中任意一个结点开始,每次都找一个权值最小的边,将这两个结点连接起来,然后在生成的新整体中继续找一个权值最小的边,将新整体和最小边的终点连接起来,以此往复,直到所有的结点全部被包含进来。
以此图为例,假设从0开始生成,那么第一条权值最小的边就是(0,5)所以第一次的结果如下:
2. 接下来参考(0,5)这个整体(标红)权值最小的为(0,1)故第二次将(0,1)进行连接,以此类推。
最终结果为:
我们需要建立两个数组,vset[]——标识当前结点是否被并入到树中,lowcost[]——存放当前生成树到剩余各顶点的最短边的权值。
算法的流程
①将初始点v到其他顶点的所有边当作和候选边
②重复一下步骤
a)从候选边中选出权值最小的边输出,和该边的终点一起放入树中(vset置1)
b)检查所有剩余结点vi,如果(v,vi)的权值比lowcost[vi]小, 更新lowcost.
void Prim(MGraph g,int v0,int &sum)
{
int lowcost[maxSize],vset[maxSize],v;
int i,j,k,min;
v=v0; //将初始入树结点标识为v0
for(i=0;i<g.n<++i) //循环访问图中的所有边
{
lowcost[i]=g.edges[v0][i]; //将v0到剩余结点的权值存入
vest[i]=0; //入树标识全部置成0
}
vset[v0]=1; //v0入树
sum = 0; //用来累计树的权值
for(i=0;i<g.n-1;++i)
{
min = INF; //INF可选一个比任意权值大的常量
for(j=0;j<g;++j)
{
if(vset[j]==0&&lowcost[j]<min)
{ //通过这个循环找到了最小权值
min = lowcost[j];
k=j;
}
vset[k] = 1; //当前最小权值入树
v=k;
sum+=min;
for(j=0;j<g.n;++j)
if(vset[j]==0&&g.edge[v][j]<lowcost[j])
lowcost[j]=g.edges[v]
}
}
}