构造最小生成树可以有多种算法。其中多数算法利用了最小生成树的下列一种简称为MST的性质:假设N=(V,{E}) 是一个连通网,U是顶点集V的一个非空子集。若(u,v)是一条具有最小权值边的边,其中u属于U,v属于V-U,则必存在一颗包含(u,v)的最小生成树。
Prim算法的定义:
假设N=(P,E)是连通网,TE 是 N 上最小生成树中边的集合。算法从 U={u0}(u0属于V), TE={}开始。重复执行下述操作:在所有u属于U,v属于V-U的边,(u,v)属于E中找一条最小的边(u0,v0)并入集合TE,同时v0并入U,直至U=V 为止。此时TE中必有n-1条边,则T=(V,{TE})为N 的最小生成树。
下面程序是来自大话数据结构的第七章图的最小生成树prim算法的源代码,代码写的很好,调理也很清晰,就是在lowcost和adjvex变量没有弄懂,到底做什么用,特别是adjvex数组,后来通过不停的模仿计算机执行代码,终于弄明白了,在代码的第二十七行体现了adjvex数组的作用,printf("(%d, %d)", adjvex[k], k); 输出符合条件的边,adjvex[k]中存储的正是具有最小权值边的起点。
虽然是弄明白了,还是觉得不够稳妥,翻看了数据结构(严慧敏),这本书里面就讲的比较清楚,而且代码里也通过结构体体现了lowcost数组和adjvex数组的关系。以下一段话摘自该书的第174页:
为实现这个算法需附设一个辅助数组closedge,以记录从U到V-U具有最小代价的边。对每个顶点Vi属于V-U,在辅助数组中存在一个相应分量closedge[i-1],它包括两个域,其中lowcost存储该边上的权。显然,closedge[i-1].lowcost = Min{cost(u, vi)|u属于U}。vex域存储该边依附的在U中的顶点。
记录从顶点集 U 到 V-U的代价最小的边的辅助数组的定义:
struct{
VertexType adjvex;
VRType lowcost;
}closedge[MAX_VERTEX_NUM];
void MiniSpanTree_Prim (MGraph G)
{
int min, i , j, k;
int adjvex[MAXVEX];
int lowcost[MAXVEX];
lowcost[0] = 0;
adjvex[0] = 0;
for( i = 1; i < G.numVertexes; i++)
{
lowcost[i] = 0;
adjvex[i] = 0;
}
for( i = 1; i < G.numVertexes; i++)
{
min = INFINITY;
j = 1;
k = 0;
while( j < G.numVertexes )
{
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;
}
}
}
}