实验报告
课程名称《算法分析与设计》
实验名称 最小生成树
1.问题
(1)举一个实例,画出采用Prim算法构造最小生成树的过程,并按实验报告模板编写算法。
(2)举一个实例,画出采用Kruskal算法构造最小生成树的过程,并按实验报告模板编写
2.解析
Kruskal算法:
假设WN=(V,{E})是含有n个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含n个顶点,而边集为空的子图,若将孩子图中各个顶,点看成是各棵树上的根节点,则它是一个含有n棵树的一个森林。之后,从网的边集E中选取一条权值最小的边,若该条边的两个顶点分属不同的树,
则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而一个取下一条权值最小的边再试试。以此类推,直至森林中只有一颗树,也即子图中含有n-1条边为止。
3.设计
Kruskal算法:
void Kruskal(Edge E[],int n,int e)
{
int i,j,m1,m2,sn1,sn2,k;
int vset[MAXE];
for(i=0;i<n;i++)
vest[i]=i; //初始化辅助数组
k=1; //k表示当前构造的第几条边,初值为1
J=0; //E中边的下标,初值为0;
while(k<n) //生成的边数小于n时循环
{
m1=E[j].u;m2=E[j].v; //取一条边的头尾顶点
sn1=vest[m1];sn2=vset[m2];//分别得到两个顶点所属的集合编号
if(sn1!=sn2) //两顶点属于不同的集合,该边是最小生成树的一条边
{
printf(“%d,%d):%d\n”,m1,m2,E[j].w);
k++; //生成边数增1
for(i=0;i<n;i++) //两个集合统一编号
{
if(vset[i]==sn2) //集合编号为sn2的改为sn1
vset[i]=sn1;
}
j++; //扫描下一条边
}
}
Prim算法:
void prime (MGraph g.int v)
{
int lowcost[MAXV];
int min;
int closest[MAXV];
int i,j,k;
for(i=0;i<g.vexnum;i++)
{
lowcost[i]=g.edges[v][i];
closest[i]=v;
}
for(j=0;j<g.vexnum;j++)
{
if(lowcost[j]!=0&&lowcost[j]<min)
{
min=lowcost[j];
k=j;
}
printf(“bian(%d,%d)权为:%d\n”,closest[k],k,min);
lowcost[k]=0;
for(j=0;j<g.vexnum;j++)
{
if(g.edges[k][j]=0&&g.edges[k][j];
closest[j]=k;
}
}
4.分析
Prime算法复杂度T(n)=n2。
kruskal算法复杂度也为n2。
5.源码
Prime:https://github.com/zbadbx/suanfa/blob/main/prime
Kruskal:https://github.com/zbadbx/suanfa/blob/main/kruskal