最小生成树 -----普里姆(prim)算法+ 邻接矩阵:
这里采用邻接矩阵的方式存储。
prim算法:用两个集合表示,v集合表示选中的顶点,u-v表示待选的顶点的集合。主要是不断的选则两集合之间边值最小的u-v中的顶点。直到顶点全部选完。
算法的主要思想是定义了两个数组:lowcost[]:用来表示两个集合之间最小的权值边。 lowset[]:用来 表示最小边对应在v集合里的顶点。
代码如下:
#include <stdio.h>
#include <malloc.h>
#define inf 330
#define max 50
typedef struct node{
int no;
}bnode;//顶点结构体
typedef struct graph{
int a[max][max];
int e,n;
bnode nu[max];
}G;//邻接矩阵结构体
//创建邻接矩阵
void create(G &g, int b[max][max], int n, int e)
{
int i ,j;
g.e =e;//边数
g.n =n;//顶点数
for(i = 0; i<n; i++)
{
for(j = 0; j <n; j++)
g.a[i][j] = b[i][j];
}
for(int i=0; i<n; i++)
g.nu[i].no = i;
}
void show(G g)
{
int i ,j;
printf("创建的邻接矩阵:\n");
//下面代码段是显示矩阵的行列标识
printf(" ");
for(int i =0; i<g.n; i++)
printf("%d ",i);
printf("\n");
for(i =0; i<g.n; i++)
{
printf("%d: ",i);
for(j=0; j<g.n; j++)
{
if(g.a[i][j] == inf)
printf(" ∞") ;
else
printf(" %d ",g.a[i][j]);
}
printf("\n");
}
printf("\n%d个顶点,%d条边 \n",g.n, g.e);
}
//普里姆算法
/*算法的主要思想是贪心的思想,就是局部优到整体。
这里主要注意两个问题:一个是找顶点问题,二是修改边值问题(修改lowcost[j]) ,前者找顶点是找在U-V集合中找最近,且边值最小的
后者就是在找到顶点的基础上修改lowcost[j],这里的lowcost[j](j是U-V集合里的顶点)指的是顶点j到集合V的最短的边值,
刚开始初始化是与0编号顶点连接的权值。
需要注意的是,如果(U-V)集合里的一个顶点与V集合有多边的时候,lowcost也是选择最喜小的一条。
*/
void prim(G g,int v)
{
int k,min,minweight =0;
int lowcost[max];//U-V集合的点到V集合点的最短的权值边
int lowset[max];//记录U-V集合里点j 最短边 在V集合里另外一端的点
//第一个循环初始化lowcost和lowset数组
for(int i =0; i<g.n; i++)
{
lowcost[i] = g.a[v][i];
lowset[i] = v;
}
//这个循环是找到顶点,顶点的范围应该是n-1
for(int i=1; i<g.n; i++)
{
min = inf;
//这个for循环,是找到最近的的顶点,这个点最近同时边值相比其他顶点的边值最小
for(int j = 0; j<g.n; j++)
if(lowcost[j]!=0 && lowcost[j] < min) //找其他顶点
{
min =lowcost[j];
k = j;
}
printf("边(%d , %d)权为:%d\n",lowset[k],k,min);
minweight +=min;
lowcost[k] = 0;//将其方法哦V集合中
//这个for循环,是上面找到的顶点,紧接着就是以该顶点为起始点,修改U-V集合得顶点到V集合的的边值
//找其他顶点,找到的顶点如果比原来连接到v集合的lowcost要小,就更新lowcost。
for(int j=0; j<g.n; j++)
if(g.a[k][j]!=0&&g.a[k][j]<lowcost[j])
{
lowcost[j] = g.a[k][j];
lowset[j] = k;
}
}
printf("\n普里姆算法生成的权值和最小值为:%d \n",minweight);
}
int main()
{
G g; //注意,这里创建的是结构体类型变量,如果是结构体指针的话,创建的矩阵就是链式
int a[max][max]={
{0,5,8,7,inf,3},
{5,0,4,inf,inf,inf},
{8,4,0,5,inf,9},
{7,inf,5,0,5,6},
{inf,inf,inf,5,0,1},
{3,inf,9,6,1,0}
};
int n=6, e=10;
//创建邻接矩阵
create(g,a,n,e);
show(g);
printf("\n普里姆算法求解结果:\n");
prim(g,0);
return 0;
}
程序运行如下: