普里姆算法是生成最小生成树的经典算法,首先是代码,然后对代码的解释。
void MiniSpanTree(MGraph *G) //采用领接矩阵的方法表示图
{
int min, i, j, k;
int adjvex[MaxVex]; //保存相关顶点下标
int lowcost[MaxVex]; //保存相关顶点间边的权值
lowcost[0] = 0; //lowcost[i] = 0就表示vi顶点加入了最小生成树。初始化第一个权值为0,即V0加入生成树
adjvex[0] = 0; //初始化第一个顶点下标为0
for (i=1; i<G->numVertexes; ++i)
{
lowcost[i] = G->arc[0][i];
adjvex[i] = 0; //将v0顶点与之有边的权值存入数组 并初始化都为v0的下标
}
for (i=1; i<G->numVertexes; ++i)
{
min = INFINITY; //INFINITY = 65535
j = 1; //顶点下标值循环变量
k = 0; //k为最小权值的顶点下标
while (j<G->numVertexes)
{
//如果两个顶点之间存在边并且权值小于min
if (lowcost[j]!=0 && lowcost[j]<min)
{
min = lowcost[j];
k = j;
}
++j;
}
printf("(%d, %d)", adjvex[k], k);
lowcost[k] = 0;
for (j=1; j<G->numVertexes; ++j)
{
if (lowcost[j]!=0 && G->arc[k][j]<lowcost[j])
{
lowcost[j] = G->arc[k][j];
adjvex[j] = k;
}
}
}
}
一、第一个for循环:初始化
lowcost[]:{0,10,65535,65535,65535,11,65535,65535,65535}
adjvex[]: {0,0,0,0,0,0,0,0,0}
二、第二个for循环:
1、i = 1时,min = 65535
while (j<G->numVertexes)
{
//如果两个顶点之间存在边并且权值小于min
if (lowcost[j]!=0 && lowcost[j]<min)
{
min = lowcost[j];
k = j;
}
++j;
}
while(j<G->numVertexes) 循环,if (lowcost[j]!=0 && lowcost[j]<min) ,其中,lowcost[j]!=0表示顶点vj没有加入最小生成树。j从1开始取值:
j = 1: Lowcost[1] = 10且<65535,所以min = lowcost[1] = 10,k = j = 1。
j = 2: Lowcost[2] = 65535>min = 10,所以不执行if循环。
j = 3,4,同理,不执行if循环。
j = 5:Lowcost[5] = 11>min = 10,所以不执行if循环。
j = 6,7,8.同理,不执行if循环。
此时,有min = 10,k = 1。
printf("(%d, %d)", adjvex[k], k); 打印结果为(0,1)
lowcost[k] = 0; 表示将v1加入最小生成树
此时,有
lowcost[]:{0,0,65535,65535,65535,11,65535,65535,65535}
adjvex[]: {0,0,0,0,0,0,0,0,0}
三、第三个for循环,j由1到8
if (lowcost[j]!=0 && G->arc[k][j]<lowcost[j]) ,因为lowcost[0]、lowcost[1]都为0,所以从j = 2开始。其中k = 1。
j = 2: lowcost[2] = 65535,G.arc[1][2] = 18 <lowcost[2] ,执行if循环有:
lowcost[2] =G.arc[1][2] = 18,adjvex[2] = 1
j = 3:lowcost[3] = 65535,G.arc[1][3] = 18 不< lowcost[3] ,不执行if循环
j = 4:lowcost[4] = 65535,G.arc[1][4] = 65535 不< lowcost[4] ,不执行if循环
j = 5: lowcost[3] = 65535,G.arc[1][5] = 65535 不<lowcost[5] ,不执行if循环
j = 6: lowcost[3] = 65535,G.arc[1][6] = 16 <lowcost[6] ,执行if循环
lowcost[6] = G.arc[1][6] = 16,adjvex[6] = 1
j = 7: lowcost[7] = 65535,G.arc[1][7] = 65535 不< lowcost[7] ,不执行if循环
j = 8: lowcost[8] = 65535,G.arc[1][8] = 12 < lowcost[8] ,执行if循环
lowcost[8] = G.arc[1][8] = 16,adjvex[8] = 1
i = 1的for 循环结束。此时:
lowcost[]:{0,0,18,65535,65535,11,16,65535,12}
adjvex[]: {0,0,1,0,0,0,1,0,1}
i = 2的循环开始,min = 65535, j = 1, k = 0
while 循环,if (lowcost[j]!=0 && lowcost[j]<min)
j = 1: Lowcost[1] = 0,不执行if循环。
j = 2: Lowcost[2] = 18 < min = 65535,所以执行if循环。
min = lowcost[2] = 18,k = j = 2
j = 3,4, 同理,不执行if循环。
j = 5: Lowcost[5] = 11 < min = 18,所以执行if循环。
min = lowcost[2] = 11,k = j = 5
j = 6,7,8. 同理,不执行if循环。
最终,有min = 11,k = 5
printf("(%d, %d)", adjvex[k], k); 打印结果为(0,5)
lowcost[k] = 0; 表示将v5加入最小生成树。
此时:
lowcost[]:{0,0,18,65535,65535,0,16,65535,12}
adjvex[]: {0,0,1,0,0,0,1,0,1}
第三个for循环,j由1到8。
if (lowcost[j]!=0 && G->arc[k][j]<lowcost[j]) ,因为lowcost[0]、lowcost[1]都为0,所以从j = 2开始。其中k = 5。
j = 2: lowcost[2] = 18,G.arc[5][2] = 65535 不< lowcost[2] ,不执行if循环
j = 3: lowcost[3] = 65535,G.arc[5][3] =65535不< lowcost[3],不执行if循环
j = 4: lowcost[4] = 65535,G.arc[5][4] =26<lowcost[4],执行if循环
lowcost[4] = G.arc[5][4] =26,adjvex[4] =5
j = 5: lowcost[5] = 0,G.arc[5][5] =0不< lowcost[5] ,不执行if循环
j = 6: lowcost[6] = 16,arc[5][6] =17不< lowcost[6] ,不执行if循环
j = 7: lowcost[7] = 65535,G.arc[5][7] = 65535 不< lowcost[7] ,不执行if循环
j = 8: lowcost[8] =12,G.arc[5][8] =65535<lowcost[8],不执行if循环
最终:
lowcost[]:{0,0,18,65535,26,0,16,65535,12}
adjvex[]: {0,0,1,0,5,0,1,0,1}
然后,进行i = 3,4,5,……8的循环,最终得出最小生成树