最小生成树的课程设计.docx
《最小生成树的课程设计.docx》由会员分享,可在线阅读,更多相关《最小生成树的课程设计.docx(18页珍藏版)》请在冰豆网上搜索。
![最小生成树的课程设计.docx](https://file1.bdocx.com/fileroot1/2022-10/28/d382079d-f4f5-4048-8e82-0efed8c5c621/d382079d-f4f5-4048-8e82-0efed8c5c6211.gif)
最小生成树的课程设计
SHENYANGUNIVERSITYOFTECHNOLOGY
数据结构与算法
课程设计报告
课程设计题目:
构造可以使n个城市连接的最小牛
成树
专业班级:
信息与计算科学1001班
姓名:
学号:
设计时间:
2011-12-26
批阅时间:
指导教师:
成
绩:
构造可以使n个城市连接的最小生
成树
主要任务:
给定一个地区的n个城市间的距离网,用Prim算法或Kruskal算法建立最小生成树,并计算得到的最小生成树的代价。
设计该程序的基本要求:
1、城市间的距离网采用邻接矩阵表示,邻接矩阵的存储结构定义采用课本中给出的定义,若两个城市之间不存在道路,则将相应边的权值设为自己定义的无穷大值。
要求在屏幕上显示得到的最小生成树中包括了哪些城市间的道路,并显示得到的最小生成树的代价。
2、表示城市间距离网的邻接矩阵(要求至少6个城市,10条边)
3、最小生成树中包括的边及其权值,并显示得到的最小生成树的代价。
总体设计
《1》该程序的主要功能:
能实现根据输入城市的信息可以判断该城市间的
距离网是否构成最小生成树,遍历城市生成最小生成树,通过计算得到最小生成树的代价。
《2》该城市间的距离网用邻接矩阵表示
《3》用克鲁斯卡尔(Kruskal)算法建立最小生成树
详细设计说明
《1》该程序的主要功能:
能实现根据输入城市的信息可以判断出该城市间的距离网是否构成最小生成树,遍历城市生成最小生成树,通过计算得到最小生成树的代价。
该程序的模块结构功能图及主要函数如下:
精品资料
a)
int
main()
//主程序
b)
int
menu()
//菜单函数
c)
void
create()
〃输入城市信息函数
d)
void
judge()
〃判断是否能够生成最小生成树函数
e)
void
display()
//打印输出
f)
void
set()
〃初始化pre[],rank[]函数
g)
void
find()
〃判断是否构成回路函数
h)
void
Union()
〃将能构成最小生成树的边添加到一个集合
1)
void
Krushal()
//克鲁斯算法求最小生成树
体会
确定程序功能设计出总体流程对整个设计进行非常重要,明确要完成设计需要的程序算法,为整个设计流程划出大纲,可以使整个设计思路更加简单明了。
《2》构造结构体
本题为求最小生成树,先要构造一个结构体,再用邻接矩阵的形式表现出来。
#definemax20
#defineMAXLNT10
typedefstructnode/*构造一个结构体,两个城市可以看成起点和终点,之间的道路可以看成一个边*/
{
intstr;/*起点*/
intend;/*终点*/
intdis;/*距离*/
}node;
nodep[max],temp;/*p记录城市信息*/
intpre[100],rank[100];/*用于判断是否构成回路*/
arcs[][]记录城市间权值*/
intn=O,arcs[MAX_LNT][MAX_LNT];/*n表示城市个数,
《3》初始化
voidset(intx)/*初始化*/
{
pre[x]=x;
rank[x]=0;
}
intfind(intx)/*找到这个点的祖先*/
{
if(x!
=pre[x])
pre[x]=find(pre[x]);
returnpre[x];
}
voidUnion(intx,inty)/*将这两个添加到一个集合里去*/
{
x=find(x);
y=find(y);
if(rank[x]>=rank[y])
{
pre[y]=x;
rank[x]++;
}
elsepre[y]=x;
}
该城市间的距离网使用邻接矩阵表示,邻接矩阵存储方法(数组存储方法),利
用两个数组来存储一个图。
用a[i][j]数组,利用邻接矩阵方式来储存城市与城市间信息。
voidcreate()/*输入城市信息*/
inti,j;
printf("请输入城市的个数:
\n");
scanf("%d",&n);
printf("输入%d个城市的邻接矩阵:
\n",n);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
scanf("%d",&arcs[i][j]);
}
}
《3》算法设计
(1)克鲁斯卡尔算法思想基本描述:
假设连通图N=(V,{E}),则令最小生成树的初始状态为只有n顶点而无边的非连通图T=(V,{}),图中每个顶点自成一个连通分量。
在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。
以此类推,直至T中所有顶点都在
同一个连通分量上为止。
(2)克鲁斯卡尔算法设计
a.设置计数器E,初值为0,记录已选中的边数。
将所有边从小到大排序,存
于P[]中。
b.从p[]中选择一条权值最小的边,检查其加入到最小生成树中是否会构成回
路,若是,则此边不加入生成树;否则,加入到生成树中,计数器E累加1
c.从E中删除此最小边,转
d.判断是否构成回路的方法:
voidKruskal()
{
intans=O,i,j,k=0;
intindex;
intcount=0;
for(i=1;i<=n;i++)
set(i);
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
p[++k].str=i;p[k].end=j;
p[k].dis=arcs[i][j];/*
}
b继续执行,直到k=n-1,算法结束
/*ans用来记录生成最小树的权总值*/
/*记录打印边的条数*/
/*初始化数组pre[x],rank[x]*/
先把所有城市之间的路段看成一个边*/
}
for(i=1;i<=k;i++)/*把所有的边按从小到大进行排序*/
{
index=i;
for(j=i+1;j<=k;j++)if(p[j].dis
temp=p[index];
p[index]=p[i];
p[i]=temp;
}
for(i=1;i<=k;i++)
{
if(find(p[i].str)!
=find(p[i].end))/*如果这两点连接在一起不构成一个回路,则执
行下面操作*/
{
printf("\t第%d条路段为:
%d--%d,权值为%d\n",++
count,p[i].str,p[i].end,p[i].dis);/*将这条边的起点、终点打印出来*/
ans+=p[i].dis;/*说明这条路段要用*/
Union(p[i].str,p[i].end);
}
}
printf("\t遍历所有城市得到最小生成树的代价为:
%d\n\n",ans);
}
设置集合S,其中存放已加入到生成树中的边所连接的顶点集合,当一条新的
边要加入到生成树中时,检查此边所连接的两个顶点是否都已经在S中,若是
则表示构成回路,否则,若有一个顶点不在S中或者两个顶点都不在S中,
则不够成回路。
voidjudge()/*判断是否能够生成最小生成树*/
{
intclose[100],low[100],i,j,ans=0;/*close[j]表示离j最近的顶点,low[j]表示离j最短的
距离*/
intuse[100];
use[1]=1;
for(i=2;i<=n;i++)
{
low[i]=arcs[1][i];/*初始化*/
close[i]=1;
use[i]=0;
}
for(i=1;i{
intmin=100000000,k=0;
for(j=2;j<=n;j++)
{
if(use[j]:
==0&&min>low[j])/*找到最小的low[]值,并记录*/
{
min=low[j];
k=j;
}
}
for(j=2;j<=n;j++)
{
if(use[j]=
=0&&low[j]>arcs[k][j])
{
low[j]=arcs[k][j];/*修改low[]值和close[]值*/
close[j]=k;
}
}
ans+=arcs[close[k]][k];
}
if(ans>=100000000)printf("不能构成最小生成树\n");
else
printf(”能构成最小生成树\n");
}
克鲁斯卡尔算法(Kruskal'salgorithm)是两个经典的最小生成树算法的较为简单理解
的一个。
这里面充分体现了贪心算法的精髓。
克鲁斯卡尔算法生成最小生成树的过程
(3)防止不能构成最小生成树的图
为避免输入的图构成的不是连通图,设计了judge()函数来判断输入数据构成的是否为连通图,此函数的主要算法是源于普里姆(PRIM)算法,经过改编,形成了新的函数。
《4》主函数的设计
intmain()/*主函数*/
{
while
(1)
{
switch(menu())
{
case1:
create();break;/*输入城市信息*/
case2:
judge();break;/*判断是否能够生成最小生成树*/
case3:
display();break;/*显示生成的最小生成树*/
case4:
exit(0);
}
return0;
}
调试与测试
网络图
GE
16
20
19
od
A
16
O0
11
CO
6
5
20
11
od
22
14
QO
19
cd
22
□0
18
oO
od
6
14
18
od
9
V
5
□0
9
y
邻接矩阵
生成界面
2011^12^293
求最小生成树
43
权
Si自st取信一成ES市之leKn有替帰U1234
请输入所选功百別-4
输入城市间信息
2011^12^290
求最小生成树
S4
枫
I
艺成
T生
亲
信一成
间构帀
±1
市否有
入断历岀
WWS
1234
请输人所选功冃也-4
詁输入城市的个数=
2011^12^290
求最小生成树
请输入所选功月也Y
请输入城市的个数醫
為入石个城市的邻接矩阵:
主成尘意个最信一成S^H间构市之
市否有入断历岀H1234
I月输入所选功能—4
器输入城市的个数:
爲入石个城市的邻接矩阵:
100061628±91003010000
1610000111000