数据结构实验 最小生成树.docx
《数据结构实验 最小生成树.docx》由会员分享,可在线阅读,更多相关《数据结构实验 最小生成树.docx(8页珍藏版)》请在冰豆网上搜索。
数据结构实验最小生成树
数据结构实验报告
最小生成树问题
一、问题描述:
若要在n个城市之间建设通信网络,只需要架设n-1条线路即可。
如何以最低的经济代价建设这个通信网,是一个网的最小生成树问题
基本要求
(1)从文件中读入图的信息。
(2)利用克鲁斯卡尔算法求网的最小生成树。
(3)以文本形式生成树中各条边以及他们的权值。
二.需求分析:
1、需定义结构体数组,根据权值逐一选择边。
三.概要设计
抽象数据类型:
需定义结构体数组,存储每条边的起点,终点,权值。
算法的基本思想:
1、图的信息的读取:
定义结构体数组,存储每条边的起点,终点,权值。
2、对每条边在数组中的位置处理:
选边需从最小的开始,故按边的权值从小到大进行排序。
3、边的选取:
从最小的边的开始,若边的两端点不属于同一集合,则选
取该边。
并将该边的两个顶点所在的两个集合合并成为一个。
因为有n个顶点,故只需选取n-1条边。
程序的流程:
(1)输入模块:
读入图的信息(顶点和边,用结构体数组进行存储)。
(2)处理模块:
Kruskal算法。
(3)输出模块:
将结果输出。
四.详细设计:
算法的具体步骤:
structG{
intfromvex;
intendvex;
intweight;
}GE[100],cur[100];
voidswap(G*GE,inti,intj){//交换函数
inttemp=GE[i].fromvex;
GE[i].fromvex=GE[j].fromvex;
GE[j].fromvex=temp;
temp=GE[i].endvex;
GE[i].endvex=GE[j].endvex;
GE[j].endvex=temp;
temp=GE[i].weight;
GE[i].weight=GE[j].weight;
GE[j].weight=temp;
}
voidKruskal(intn){
inti,j,k=0,pos=-1,m1,m2;
bool**s=newbool*[n];
//定义一个二维数组,用来判断是否为同一类
for(i=0;is[i]=newbool[n];
for(i=0;ifor(j=0;j{
if(i==j)
s[i][j]=true;//初始化数组
else
s[i][j]=false;
}
}
while(kfor(i=0;iif(s[i][GE[k].fromvex]==1)
m1=i;
if(s[i][GE[k].endvex]==1)
m2=i;
}
if(m1!
=m2){
//判断是否为同一类,如果为同一类(该类中所有的点到起点和终//点的边在s数组中赋为1),
cur[++pos].fromvex=GE[k].fromvex;
cur[pos].endvex=GE[k].endvex;
cur[pos].weight=GE[k].weight;
for(i=0;iif(s[m1][i]||s[m2][i])
//把该点添加到该类,并和并两个类
s[m1][i]=1;
else
s[m1][i]=0;
s[m2][i]=0;
}
}
k++;
}
for(i=0;idelete[]s[i];
}
}
intmain(){
inti,j;
intnumVertex,numEdge;
cout<<"请输入点的个数和边的条数:
"<cin>>numVertex>>numEdge;
cout<<"请输入边的起始位置和边的权值:
"<for(i=0;icin>>GE[i].fromvex>>GE[i].endvex>>GE[i].weight;
for(i=0;ifor(j=i;jif(GE[j].weight//将边的权值按从小到大排列
swap(GE,i,j);
}
Kruskal(numEdge);
for(i=0;icout<"<"<system("pause");
return0;
}
五.调试分析:
将选边的过程输出来检验算法的正确性。
六.测试结果:
七.实验心得:
1、一开始我不会二维数组的动态分配,这次通过查阅资料掌握了
该方法,让我学到了新知识。
2、在一开始写程序时,只是把一个点添加到一个类中。
后来分析
才改正错误,将两个集合进行合并。
3、曾试图用两个顶点是否有同一个根结点来判断两点是否为同
一集合的,但未实现。
八、附件
最小生成树问题.cpp
最小生成树问题.exe
代码:
#include
usingnamespacestd;
structG{
intfromvex;
intendvex;
intweight;
}GE[100],cur[100];
voidswap(G*GE,inti,intj){//交换函数
inttemp=GE[i].fromvex;
GE[i].fromvex=GE[j].fromvex;
GE[j].fromvex=temp;
temp=GE[i].endvex;
GE[i].endvex=GE[j].endvex;
GE[j].endvex=temp;
temp=GE[i].weight;
GE[i].weight=GE[j].weight;
GE[j].weight=temp;
}
voidKruskal(intn){
inti,j,k=0,pos=-1,m1,m2;
bool**s=newbool*[n];//定义一个二维数组,用来判断是否为同//一类
for(i=0;is[i]=newbool[n];
for(i=0;ifor(j=0;j{
if(i==j)
s[i][j]=true;//初始化数组
else
s[i][j]=false;
}
}
while(kfor(i=0;iif(s[i][GE[k].fromvex]==1)
m1=i;
if(s[i][GE[k].endvex]==1)
m2=i;
}
if(m1!
=m2){//判断是否为同一类,如果为//同一类(该类中所有的点到起点和终点的边在s数组中赋为1),
cur[++pos].fromvex=GE[k].fromvex;
cur[pos].endvex=GE[k].endvex;
cur[pos].weight=GE[k].weight;
for(i=0;iif(s[m1][i]||s[m2][i])//把该点添加到该类,并和并两个类
s[m1][i]=1;
else
s[m1][i]=0;
s[m2][i]=0;
}
}
k++;
}
for(i=0;idelete[]s[i];
}
}
intmain(){
inti,j;
intnumVertex,numEdge;
cout<<"请输入点的个数和边的条数:
"<cin>>numVertex>>numEdge;
cout<<"请输入边的起始位置和边的权值:
"<for(i=0;icin>>GE[i].fromvex>>GE[i].endvex>>GE[i].weight;
for(i=0;ifor(j=i;jif(GE[j].weightswap(GE,i,j);
}
Kruskal(numEdge);
for(i=0;icout<"<"<system("pause");
return0;
}