//核心 Prim算法求最小生成树
/*
编一C程序,它能根据输入数据构造带权无向图G,
并输出G的最小生成树。
图的输入形式为n V0 Vi0 w0 V1 Vi1 w1 V2 Vi2 w2 ...Vi Vin wn -1 -1 -1(-1,-1,-1为输入结束标记,其余的值都>=0且<n),它们都是整数,且100>n>0。
*/
#include <stdio.h>
#define infinity 1000000 //常数infinity为无穷大
#define max_vertexes 100 //常数max_vertexes为图最大节点数
void prim(int G[][max_vertexes],int vcount,int father[]);
int juZhen(int g[][max_vertexes]);
void main()
{
int g[max_vertexes][max_vertexes];
int vcount=0,father[max_vertexes];
vcount=juZhen(g); //初始化矩阵
printf("该图的最小生成树为\n");
prim(g,vcount,father);
}
/*
lowcost: 记录权值的
used[]: //记录每个顶点是否被并入:默认值为0;当并入后修改对应值为1
father[]:
closeset[]:
*/
void prim(int G[][max_vertexes],int vcount,int father[])
{
int i,j,k,m=0;
int lowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes];
int min;
//初始化------------------------------------
for (i=0;i<vcount;i++)
{
used[i]=0;
closeset[i]=0;
father[i]=-1;
}
//------------------------------------------------
used[0]=1; //把第0个顶点归入集合u中
for(i=0;i<vcount;i++)
{
lowcost[i]=G[0][i]; //把各顶点到顶点0的权值保存在lowcost[i]中
}
//----------------------------------------------------
for (i=1;i<vcount;i++) //循环次数:n个顶点,进行n-1次即可 ( u={v0}, 剩下的顶点{v1,.......} 开始生成最小生成树)
{
//求最小值
min=infinity;
for(m=0;m<vcount;m++)
{
if(used[m]==0 && lowcost[m]<min)
{
min=lowcost[m];
j=m;
}
}
father[j]=closeset[j]; //记录j的前领结点
used[j]=1; //把顶点j并入u中
for (k=0;k<vcount;k++) //新顶点并入u后重新选择最小边(针对lowcost[k]的修改)
{
if (!used[k]&&(G[j][k]<lowcost[k]))
{
lowcost[k]=G[j][k];
closeset[k]=j;
}
}
}
//自己加的:最小生成树的生成
for(m=0;m<vcount;m++)
{
if(father[m]!=-1)
{
printf("v%d-v%d\t",father[m],m);
}
}
}
int juZhen(int g[][max_vertexes])
{
int vCount=0,i=0,j=0,w=0,m=0,n=0;
printf("功能:依输入数据构造带权无向图G,并输出G的最小生成树\n\n");
printf("请输入图的顶点数,范围在1-%d\n",max_vertexes); //输入顶点个数
scanf("%d",&vCount);
while(vCount<0 || vCount>max_vertexes)
{
printf("顶点个数输入有误,请重新输入");
scanf("%d",&vCount);
}
printf("则顶点的范围在0-%d\n",vCount-1);
for(m=0;m<vCount;m++) //图的矩阵初始化
{
for(n=0;n<vCount;n++)
{
g[m][n]=infinity; //默认权值为无穷大
}
}
printf("请输入图中边所连顶点i与j,及边的权值,以 -1 -1 -1为结束标志\n"); //图的矩阵
scanf("%d %d %d",&i,&j,&w);
while(i!=-1 && j!=-1 && w!=-1)
{
//对顶点i j范围限制
if(i<0 ||i>=vCount || j<0 ||j>=vCount)
{
printf("顶点输入有误,请重新输入\n");
continue;
}
else
{
g[i][j]=w;
g[j][i]=w;
}
scanf("%d %d %d",&i,&j,&w);
}
return vCount;
}
求图的最小生成树(prim算法
最新推荐文章于 2019-12-25 14:37:44 发布
