计算最小生成树的一种方法就是使其连续的一步一步的长成。在每一步都要把一个结点当做根来往上加边。在算法的任一时刻都可以看到一组已经添加到树上的顶点,而其余顶点尚未加到这棵树上。就找尚未加到这个树上的顶点到已经加到树上的顶点的最小的权值。
以v1作为起始点,这时v4与v1的权值最小,那么就把v1和v4连上;
然后在其他没有被连在树上的顶点中找到了v2里v1权值是2,v3离v4权值是2,这两个最小,那么就再把v2和v3加入到树中;
接下来在剩下没有加到树中的有v5,v6,v7,可以看到v7离已经被到树中的v4的权值是4,这是最小的,那就把v7连进去;
这时候剩v5和v6,v6离已经被到树中的v7的权值是1,这是最小的,所以把这条连进去;
最后v5与个点中权值最小的是v5和v7为6,连进去。
结果就是这样。
上代码:
#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 7
#define INFINITY 65535 //代表无穷大
typedef struct
{
char vex[MAXVEX];
int arc[MAXVEX][MAXVEX];
int vertex,edge; //顶点数量和边的数量
}Graph;
//创建邻接矩阵
void createGra(Graph *g)
{
int i,j;
printf("请输入顶点数量和边的数量:\n");
scanf("%d %d",&g->vertex,&g->edge);
printf("输入顶点元素\n");
for(i=0;i<g->vertex;i++)
{
getchar();
scanf("%c",&g->vex[i]);
}
//建立矩阵
printf("如果有连线就输入其权值,i与j相等的时候是0,否则是无穷大:\n");
for(i=0;i<g->vertex;i++)
{
for(j=0;j<g->vertex;j++)
{
scanf("%d",&g->arc[i][j]);
}
}
}
//输出邻接矩阵
void print(Graph g)
{
int i,j;
for(i=0;i<g.vertex;i++)
{
for(j=0;j<g.vertex;j++)
{
printf("%8d ",g.arc[i][j]);
}
printf("\n");
}
printf("\n");
}
//prim算法
void prim(Graph g)
{
int i,j,k,sum=0;
int min;
int adjvex[MAXVEX]; //保存相关顶点
int lowcost[MAXVEX]; //保存已经连接了的顶点的权值
//初始化,从下标是0的顶点开始
for(i=0;i<g.vertex;i++)
{
adjvex[i]=0;
lowcost[i]=g.arc[0][i]; //存第一个顶点的所有的权值
}
for(i=0;i<g.vertex;i++)
{
min = INFINITY;
j=1;
k=0;
while(j<g.vertex)
{
if(lowcost[j]!=0 && lowcost[j]<min)
{
min=lowcost[j]; //找到与顶点相连的最小的权值下标
k=j;
}
j++;
}
if(min!=INFINITY) //一开始没有加这个if 但是结果发现多出来一个(0,0),权值多出65535,调试发现是最后一次循环又把min初始化然后输出了
{
printf("(%d,%d) ",adjvex[k],k);
lowcost[k]=0; //表明k下标已经是遍历过了的,接下来遍历就不会找到k和i边了
printf("权值为:%d",min);
sum=sum+min;
}
for(j=1;j<g.vertex;j++)
{
if(lowcost[j]!=0 && g.arc[k][j]<lowcost[j])
{
lowcost[j]=g.arc[k][j]; //找到已经遍历了的顶点和没有遍历的的顶点的权值较小的存到了lowcost中,
adjvex[j]=k; //作为等会打印的上一个顶点
}
}
}
printf("\n最小权值和为%d\n",sum);
}
int main()
{
Graph g;
createGra(&g);
print(g);
prim(g);
return 0;
}
学习《数据结构与算法分析》的笔记。