Prim算法的思想:从图中任意取出一个顶点,把它当成一棵树,然后从与这颗树相接的边中选取一条最短(权值最小)的边,并将这条边及其多连接的顶点也并入这棵树中,此时得到了一棵有两个顶点的树,然后从与这棵树相接的边中选取一条最短的边,并将这条边及其所连顶点并入当前树中,得到一棵含有3个顶点的树,一次类推。。。
代码如下:
/*构造一张无向图*/
#ifndef MGRAPH_H_
#define MGRAPH_H_
#define INF 9999
#define maxSize 30
typedef int VertexType;
typedef struct
{
int edges[maxSize][maxSize];
int n,e;
VertexType vex[maxSize];
}MGraph;
void CreateMGraph( MGraph * G)
{
int i,j,k,weight;
int n1,n2;
printf("请输入顶点数和边数(输入格式为:顶点数,边数):\n");
scanf("%d,%d",&(G->n),&(G->e));
//给顶点编号
for(i=0;i<G->n;i++)
G->vex[i]=i;
for(i=0;i<G->n;i++)
for(j=0;j<G->n;j++)
{
G->edges[i][j]=INF;
if(i==j)
G->edges[i][j]=0;//邻接矩阵的对角线为0
}
printf("请输入对应的边的结点号和边的权值(i,j,w)\n");
for(k=0;k<G->e;k++)
{
printf("第%d条边的结点号和权值:",k+1);
scanf("%d,%d,%d",&i,&j,&weight);
G->edges[i][j]=weight;
G->edges[j][i]=weight;
}
}
#endif
头文件MGraph.h结束
#include<stdio.h>
#include"MGraph.h"
typedef enum {NO,YES} Bool;
Bool vset[maxSize];
void Prim(MGraph const G,int const v0,int * sum)
{
int lowcost[maxSize],v;//lowcost保存的是当前生成树到顶点的最短边的权值
int i,j,k,min;
v=v0;
for(i=0;i<G.n;i++)
{
lowcost[i]=G.edges[v0][i];
vset[i]=NO;
}
vset[v0]=YES;
printf("%d",v0);
*sum=0;//sum 清零用来累计树的权值
for (i=0;i<G.n-1;i++)
{
min=INF;
/*下面这个循环用于选出候选边中的最小者*/
for(j=0;j<G.n;j++)
if(vset[j]==NO && lowcost[j]<min)
{
min=lowcost[j];
k=j;
}
vset[k]=YES;
v=k;
*sum=(*sum)+min;
printf(" %d",k);
/*以刚并入的顶点V为媒介更新候选边*/
for(j=0;j<G.n;j++)
if(vset[j]==NO&&G.edges[v][j]<lowcost[j])
lowcost[j]=G.edges[v][j];
}
}
void main(void)
{
MGraph G;
int sum=0;
int i;
CreateMGraph(&G);
Prim(G,0,&sum);
printf("%d",sum);
}