基本概念:
生成树:一个连通图的生成树是它的一个极小连通子图
从生成树的定义可知,一个连通图的生成树含有图的全部n个顶点和n-1条边。
最小生成树(minimal spanning tree):给连通图的边附上权值,则其所有权值之和最小的生成树是最小生成树。
Prim算法构造最小生成树:
假设有连通图G=(V,E),其最小生成树表示为G’=(U,TE)。
- 从V中选择一个顶点v作为起点加入到U中,将v到其他顶点的所有边作为候选边(三类:到自身(权值为0)、到邻接点、到非邻接点(权值为∞))
- 重复以下步骤直到其他n-1个顶点加入到U中:
1)从候选边中选择最小边(权值最小),并将其关联的顶点k加入到U;
2)考查V-U中的所有顶点j,修改候选边,如果(k,j)的权值小于原来和顶点j关联的候选边,则用前者取代后者。
代码实现:
void Prim(MatGraph *G, int v)
{
//MAXV为预处理器常量,值为顶点个数
int lowcost[MAXV];
int closest[MAXV];
int i, j, k, MIN;
for (i=0; i<G->n; i++)
{
lowcost[i] = G->edgs[v][i];
closest[i] = v;
}
for (i=1; i<G->n; i++)
{
//IFN为代表无穷大权值的预处理器常量
MIN = IFN;
for (j=0; j<G->n; j++)
if (lowcost[j] != 0 && lowcost[j] < MIN)
{
MIN = lowcost[i];
k = j;
}
printf("there is a minimal edge (%d,%d), weight:%d\n", closest[k], k, lowcost[k]);
lowcost[k] = 0;
for (j=0; j<G->n; j++)
if (lowcost[j] != 0 && G->edgs[k][j] < lowcost[j])
{
lowcost[j] = G->edgs[k][j];
closest[j] = k;
}
}
}
算法分析:Prim算法用到了两重循环,并且循环次数图的顶点个数有关,因此其时间复杂度为O(n2),而与边数无关,因此Prim算法特别适合稠密图求最小生成树。