最小生成树问题的算法实现及复杂度分析天津大学计算机科学与技术学院算法设计与分析Word文档格式.docx
- 文档编号:19230958
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:14
- 大小:114.75KB
最小生成树问题的算法实现及复杂度分析天津大学计算机科学与技术学院算法设计与分析Word文档格式.docx
《最小生成树问题的算法实现及复杂度分析天津大学计算机科学与技术学院算法设计与分析Word文档格式.docx》由会员分享,可在线阅读,更多相关《最小生成树问题的算法实现及复杂度分析天津大学计算机科学与技术学院算法设计与分析Word文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
正文
普里姆(Prim)算法思想
普里姆算法则从另一个角度构造连通网的最小生成树。
它的基本思想是:
首先选取图中任意一个顶点v作为生成树的根,之后继续往生成树中添加顶点w,则在顶点w和顶点v之间必须有边,且该边上的权值应在所有和v相邻接的边中属最小。
在一般情况下,假设图G=(V,E)中已落在生成树上的顶点集为U,则尚未落在生成树上的顶点集为V-U,则从(V-U)顶点集中选取加入生成树的顶点w应满足下列条件:
它和生成树上的顶点之间的边上的权值是在联接这两类顶点的所有边中权值属最小。
从上述生成树的构造过程中回还可以发现一点,即每个顶点都是通过"
一条边"
加入到生成树上的,因此对集合V-U中的每个顶点,当它和集合U中的顶点有一条以上的边相连时,只需要保留一条权值最小的边即可。
由此,在普里姆算法中需要附设一个辅助数组closedge,以记录从集合U到集合V-U中每个顶点当前的权值最小边。
普里姆算法构造最小生成树的过程
普里姆(Prim)算法设计:
一:
定义模块:
1.头文件、新类型及固定值定义。
本程序可接受的最大顶点数为20个,没有连接的点之间,用100表示其权值。
#include<
iostream>
usingnamespacestd;
#defineMAX_VERTEX_NUM20//最大顶点数
#defineQM100//最大值
#defineOK1
#defineERROR0
intvisited[MAX_VERTEX_NUM];
typedefintVertexType;
typedefintVRType;
2.首先设计图的存储模块,即定义类型。
本程序采用的图定义是无向图的定义方式,存储模块采用邻接矩阵,便于查找。
typedefstructArcCell//邻接矩阵的值
{
intadj;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
VertexTypevexs[MAX_VERTEX_NUM];
//顶点向量
AdjMatrixarcs;
//邻接矩阵
intvexnum,arcnum;
//图的当前顶点数和弧数
}MGraph;
3.在实现最小生成树算法时,定义辅助数组,进行判断遍历。
VertexTypeadjvex;
VRTypelowcost;
}closedge[MAX_VERTEX_NUM];
4.最后生成最小生成树时,采用辅助数组进行结果的记录。
VertexTypehead;
VRTypelast;
intweight;
}result[MAX_VERTEX_NUM];
二:
实现模块(函数)
1.顶点查找函数,因为顶点的值和数组位置的下标不一定相等,所以加入顶点查找函数,返回顶点的值,便于结果显示、区分指针与内容,使思路更为清晰。
intLocateVex(MGraph&
G,VertexTypev)//确定顶点位置
intk;
for(k=0;
k<
G.vexnum;
k++)
{
if(G.vexs[k]==v)
returnk;
}
return-1;
//没有这个顶点
}
2.无向图的创建函数。
intCreateUDN(MGraph&
G)//创建无向图
inti,j,k;
VertexTypev1,v2;
cout<
<
"
输入无向图的顶点数和弧数:
endl;
cin>
>
G.vexnum>
G.arcnum;
for(i=0;
i<
++i)
for(j=0;
j<
++j)
G.arcs[i][j].adj=QM;
输出网的"
G.vexnum<
个顶点(限数字):
i++)
cin>
G.vexs[i];
建立弧,请输入"
G.arcnum<
条弧的顶点和权值(v1,v2,w):
v1>
v2>
weight;
i=LocateVex(G,v1);
j=LocateVex(G,v2);
if(i<
0||j<
0)
returnERROR;
G.arcs[i][j].adj=weight;
G.arcs[j][i].adj=G.arcs[i][j].adj;
returnOK;
3.最小生成树建立主程序,采用借助辅助数组的方式,对于辅助的数组,以邻接表的选择点加入该数组,然后查找数组中权值最小,且未被选中的顶点,然后返回该边,加入最小生成树中。
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu)
closedgedge;
//申请数组
resultpax;
intk,j,i,lax,time=0,x,y;
lax=G.vexnum-1;
k=LocateVex(G,u);
//确定初始结点的下标
++j)//初始化临时辅助数组
if(j!
=k)
{
dge[j].lowcost=G.arcs[k][j].adj;
//数组中的adjvex均为u,即从u开始到所有其他结点的权值赋给了数组中lowcost
dge[j].adjvex=u;
//数组中的下标起箭头的作用,即它是边的第二个尾结点!
}
dge[k].lowcost=0;
//u在数组dge的下标即为k,故自身到自身权值标为0,也表示纳入点集V!
for(i=1;
{
k=minimun(G,dge);
//在dge数组中找到最小的一条边,并返回尾结点的下标!
cout<
K的寻求结果为(数组dge中的下标):
dge[k].adjvex<
"
G.vexs[k]<
//输出边
pax[time].head=dge[k].adjvex;
pax[time].last=G.vexs[k];
x=LocateVex(G,dge[k].adjvex);
y=LocateVex(G,G.vexs[k]);
pax[time].weight=G.arcs[x][y].adj;
time++;
dge[k].lowcost=0;
//把下标为k的结点纳入点集V!
标注权值为0!
for(j=0;
if(G.arcs[k][j].adj<
dge[j].lowcost)
{//新加入的点到其他各点的权值比原来的权值更小,则替换!
采取遍历的方法!
dge[j].lowcost=G.arcs[k][j].adj;
dge[j].adjvex=G.vexs[k];
//点的名字进行修改!
}
最小生成树为:
endl<
起点终点权值"
for(time=0;
time<
lax;
time++)
pax[time].head<
pax[time].last<
pax[time].weight<
4.辅助生成最小生成树的函数。
intminimun(MGraphG,closedgeF)
inti,min;
if(F[i].lowcost!
=0)break;
min=i;
=0&
&
F[i].lowcost<
F[min].lowcost)
min=i;
returnmin;
数组的样式:
j
Lowcost
adjvex
过程如下表:
顶点标号都比图中的小1,比如v1为0,v2为1,这里首先选择v1点。
1
2
3
4
5
100
从这个表格可以看到依附到v1顶点的v3的Lowcost最小为2,那么选择v3,选择了之后我们必须要更新Lowcost数组的值,因为记录从U到V-U具有最小代价的边,加入之后就会改变。
新加入的点到其他各点的权值比原来的权值更小,则替换!
6
Lowcost=0为我们已经选出来的顶点,接着继续在Lowcost中选出值不为0的最小值,作为下一个最小生成树的点。
这样一直选择下去直到选出所有的顶点。
5.最小生成树建立,那么需要借用辅助数组,进行记录。
6.调试时,加入的函数,输出邻接矩阵和辅助数组,进行查看和判断正误。
voidPrintMatrix(MGraph&
G)//输出邻接矩阵
inti,j;
printf("
邻接矩阵为:
\n"
);
j++)
if(G.arcs[i][j].adj!
=QM)
cout<
G.arcs[i][j].adj<
;
elsecout<
∞"
voidprintclosedge(MGraphG,closedgeX)//输出辅助建立最小生成树数组
inti;
dge数组值为:
i:
i;
lowcost:
X[i].lowcost;
adjvex:
X[i].adjvex;
7.主程序。
voidmain()
MGraphG;
VertexTypeu;
G.vexnum=G.arcnum=0;
CreateUDN(G);
PrintMatrix(G);
请输入要开始的点:
u;
MiniSpanTree_PRIM(G,u);
system("
pause"
普里姆(Prim)算法分析:
Prim算法的时间复杂度主要是在双重循环构造最小生成树的过程中,设图的顶点数为n,则双重循环的时间复杂度为O(n2),在生成最小生成树的过程中,增加了两个数组,closedge[]和result[]数组,用来记录所选顶点的全趋结点,故空间复杂度为O(2n)。
普里姆算法的时间复杂度与边数e无关,该算法更适合于求边数较多的带权无向连通图的最小生成树。
普里姆(Prim)算法实验结果:
采用的数据:
611
123456
124
143
132
253
244
235
341
362
456
462
564
实验结果:
图表分析:
2
42
3
5
41
32
6
4
(a)(b)
2
11
1
(c)(d)
42
232
(e)(f)
结论与展望:
运用prim算法构造图的最小生成树,使生成树的权值和达到最小,即耗费最小,这里选择贪心策略,从一个顶点出发,选择到剩余顶点的边权值最小的顶点,将之并入到所够造的生成树之中,同时修改剩下的顶点到生成树的权值,再从剩余顶点中继续选择到生成树耗费最小的顶点,继续并入该顶点,直到所有的顶点全部并入到生成树中为止,其核心思想在于不断地在剩余顶点中选取到生成树耗费最小的顶点,将之并入后,修改剩余顶点到生成树相应的权值,体会到了贪心思想,实验完成较为成功。
除此之外,通过本次课程设计巩固了课本的基本知识,熟练运用课程知识。
提高我们组织数据及编写程序的能力,使我们能够根据问题要求和数据对象的特性,学会数据组织的方法,把现实世界中的问题在计算机内部表示出来并用软件解决问题,本次实验大大提高了我对编程的爱好。
但对算法的时间复杂度感到略微的不足,希望将来能加以改进,实现更为简练的最小生成树算法。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 最小 生成 问题 算法 实现 复杂度 分析 天津大学 计算机科学 技术学院 设计
链接地址:https://www.bdocx.com/doc/19230958.html