prim算法生成最小生成树
先描述下prime算法:
N={V,{E}} 其中,顶点集V和边集{E}
从U={u0} u0是V的子集,TE={}开始。在所有在U中的结点和不足U中的结点中找到一条代价最小的边(u0,v0),合入TE,将v0。直到U=V。
具体实现如下:
#include <stdlib.h>
#include <stdio.h>
#define INFINITY 100
typedef struct
{
int vexs[9];
int arc[9][9];
int numVertexes,numEdges;
}MGragh;
void CreateGragh(MGragh *G)
{
int i,j,k,w;
printf("input the vex and edges:");
scanf("%d%d",&G->numVertexes,&G->numEdges);
for (i=0; i<G->numVertexes; i++)
G->vexs[i]=i;
for (i=0; i<G->numVertexes; i++)
for (j=0; j<G->numVertexes; j++)
{
G->arc[i][j]=INFINITY;
G->arc[i][i]=0;
}
printf("input the (i,j)edge's value:\n");
for(k=0; k<G->numEdges;k++)
{
scanf("%d%d%d",&i,&j,&w);
G->arc[i][j]=w;
G->arc[j][i]=G->arc[i][j];
}
}
void MiniTree_Prim(MGragh *G)
{
int min,i,j,k;
int adjvex[9];
int lowcost[9];
lowcost[0]=0;// 标记顶点0已经在U中
adjvex[0]=0;
// U中仅有v0点的初始化
for(i=1; i<G->numVertexes; i++)
{
lowcost[i]=G->arc[0][i];
adjvex[i]=0;
}
for(i=1; i<G->numVertexes; i++)
{
//从U出发的边集中,到U-V顶点集中中找到最小的边lowcost
min=1000;
j=1;k=0;
while(j<G->numVertexes)
{
if((lowcost[j]!=0)&&(min > lowcost[j]))
{
min=lowcost[j];//找到最小的边
k=j ;//找到最小的边对应在U-V中的顶点,另一顶点已经在U中
}
j++;
}
printf("(%d,%d)\n",adjvex[k],k);
lowcost[k]=0;//标记顶点k已经在U中
//看k加入U后的集合中,是否存在更短的边
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;
}
}
}
}
void main()
{
MGragh *gragh;
gragh=(MGragh *)malloc(sizeof(MGragh));
CreateGragh(gragh);
MiniTree_Prim(gragh);
system("pause");
}
输入:9 (顶点数)14(边数)
初始化边:
0 1 10
0 5 11
1 2 18
1 6 16
1 8 12
2 3 22
2 8 8
3 4 26
3 7 16
3 8 21
4 5 26
4 7 7
5 6 17
6 7 19
输出结果:
(0,1)
(0,5)
(1,8)
(8,2)
(1,6)
(6,7)
(7,4)
(7,3)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
分析,建立两个数组adjvex[MAXVEX] ; 如 adjvex[i] = j; // 表示与当前结点 i 连结的是结点 j
lowcost[MAXVEX]; 如 lowcoast[i]=j; // 表示到结点i的最小代价为j.当j=0时,表示标记该结点已经锁定为最小生成树中的结点。
#define INFINITY 65535
void MiniSpanTree_Prim(MGragh G) // 采用邻接矩阵存储边的权值
{
int min, i, j, k;
int adjvex[MAXVEX] ;
int lowcost[MAXVEX];
lowcost[0]=0; //初始化v0为第一个结点,值为0表示已经锁定。
for (i=1; i<G.numVertexes; i++)
{
lowcost[i]=G.arc[0][i];
adjvex[i]=0; //所有结点都与v0结点连边。viv0边
} //至此,初始化完成。从v0结点开始。
//下面要找与某结点(第一次是v0)连结的最小的顶点的边
for(i=1; i<G.numVertexes; i++)
{
min=INFINITY;
j=1;
k=0; //标记最小结点
while(j<G.numVertexes)
{
if (lowcost[j] != 0 && lowcost[j] < min) //遍历所有到j结点的值,找到最小。
{
min = lowcost[j];
k = j;
}
j++;
}
printf("(%d,%d)",adjVex[k],k); //找到lowcost[k]中k的l连结结点adjVex[k],组成边。即为最小生成树的其中的边。
lowcost[k] = 0;
//下面将结点k所连结的的所有结点的边信息存储。在下一次比较最小权值边时进行比较。
for (j=1; j<G.numVextexes; j++)
{
if (lowcost[j] != 0 && G.arc[k][j]<lowcost[j])
{
lowcost[j] = G.arc[k][j]; //lowcost[j]是到j 结点的最小边值
adjvex[j]=k; //重要,这里保证了通过lowcost[j]得到的 j,可以找到与它连结的结点 i .形成一条边。
}
}
}
}