1)包含任务或问题描述和分析
最小生成树其实是最小权重生成树的简称。我们称求取该生成树的问题成为最小生成树问题。一个连通图可能有多个生成树。当图中的边具有权值时,总会有一个生成树的边的权值之和小于或者等于其它生成树的边的权值之和。
2)设计与实现
利用prim算法实现最小生成树,该算法思路与Dijsktra算法大致相同,不过Prim算法的最短是相较于整体而言的,所以我将Dijsktra算法稍作改进得到Prim算法
3)测试例子与结果分析
测试例子:(图片从网上找的,当做例子,非常直观)
测试结果:
4)带注释的源代码
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 10
#define MAXROAD 999
/*
本算法由Dijsktra算法改变而来
*/
typedef struct{
int i;
int j;
int weight;
}Node;//记录最小生成树的边和权重
void Prim(int g[][MAX_SIZE],int num){//num为一开始知道的结点
int flag[MAX_SIZE]={0};//标志数组
flag[num]=1;//将初始结点放入数组
int i;
Node tree[MAX_SIZE-1];//边的数量比结点少一
for(i=0;i<MAX_SIZE-1;i++){//一共循环MAX_SIZE-1次找到这么多的边
Node temp;//记录最小的边
temp.i=0;
temp.j=0;
temp.weight=MAXROAD;//初始化Node
int j,k;
for(j=0;j<MAX_SIZE;j++)
for(k=0;k<MAX_SIZE;k++)
{
if(flag[j])
{//在已记录的结点中寻找边
if(g[j][k]<temp.weight&&flag[k]==0){
temp.i=j;
temp.j=k;
temp.weight=g[j][k];
}
}
else break;
}
flag[temp.j]=1;//标记数组更新
tree[i].i=temp.i;
tree[i].j=temp.j;
tree[i].weight=temp.weight;//更新节点数组
}
for(i=0;i<MAX_SIZE-1;i++){
if(tree[i].weight!=MAXROAD)
printf("生成树的边为结点%d---->结点%d, 权值为%d\n",tree[i].i,tree[i].j,tree[i].weight);
}
}
int main()
{
int Grape[MAX_SIZE][MAX_SIZE]={0};//该图不是有向图,所以要更新为无向图
int i,j,num;
printf("请输入i到j的路径并输入它的长度");
while((scanf("%d%d%d",&i,&j,&num))!=EOF)
{
Grape[i][j]=num;
Grape[j][i]=num;//对称为无向图
printf("请输入i到j的路径并输入它的长度");
}
for(i=0;i<MAX_SIZE;i++)for(j=0;j<MAX_SIZE;j++)if(Grape[i][j]==0)Grape[i][j]=MAXROAD;
Prim (Grape,0);
return 0;
}