1、图的遍历与最小生成树的实现 ———————————————————————————————— 作者: ———————————————————————————————— 日期: 42 个人收集整理 勿做商业用途 数学与计算机学院
2、 课程设计说明书 课 程 名 称:数据结构与算法课程设计 课 程 代 码: 题 目:图的遍历和最小生成树 年级/专业/班: 2011级软工一班 学 生 姓 名: 学 号: 开 始 时 间: 2012 年 12 月 24 日 完 成 时 间: 2012 年 1 月 3 日 课程设计成绩: 学习态度及平时成绩(3
3、0) 技术水平与实际能力(20) 创新(5) 说明书(计算书、图纸、分析报告)撰写质量(45) 总 分(100) 指导教师签名: 年 月 日 目 录 (小三黑体,居中) 引言……………………………………………………………………………1 1 需求分析…………………………………………………………………… 2 概要设计…………………………………………………………………… 3详细设计…………………………………………………………………… 4调试分析…………………………………………………………………… 5用户
4、使用说明……………………………………………………………… 6测试结果…………………………………………………………………… 7结论……………………………………………………………………… 致谢…………………………………………………………………………… 参考文献……………………………………………………………………… (目录左对齐,所有的均为1。5倍行距,未具体指明使用字体的均为小四宋体,以下同) (目录中最多放二级标题。注意看页面的规范要求。尤其注意页眉。页眉从目录开始) 摘
5、 要 图是一种比线形表和树更为复杂的数据结构.在图形结构中,节点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关.本程序是采用邻接矩阵、邻接表、十字链表等多种结构存储来实现对图的存储。采用邻接矩阵即为数组表示法,邻接表和十字链表都是图的一种链式存储结构。对图的遍历分别采用了广度优先遍历和深度优先遍历。 关键词:图;存储结构;遍历 引 言 数据结构是计算机存储、组织数据的方式,是指相互之间存在一种或多种特定关系的数据元素的集合.利用数据
6、结构能解决许多实际问题,在各个方面都有非常不错的成就. 通过本项课程设计,培养学生独立思考、综合运用所学有关相应知识的能力,使学生巩固《数据结构》课程学习的内容,掌握工程软件设计的基本方法,强化上机动手编程能力,闯过理论与实践相结合的难关;为了培养学生综合运用所学知识、独立分析和解决实际问题的能力,培养创意识和创新能力,使学生获得科学研究的基础训练。为后续各门计算机课程的学习和毕业设计打下坚实基础.同时,可以利用这次机会来检验自己的c++数据结构水平,提高自己的写作水平,锻炼自己的动手能力。 而此次课程设计的任务和意义在于:增强自己的动手能力,利用VC++6.0等专业软件编程实现图各种遍历
7、的算法,以及最小生成树算法,增强自己的调试程序和测试程序的能力. 1 需求分析 1。1任务与分析 1. 由键盘向程序输入相关数据; 2. 程序处理输入数据,以十字链表,邻接矩阵和邻接链表的形式输出; 3. 根据已建成的图,程序实现图的深度优先遍历,广度优先遍历; 4. 显示图的最小生成树,连同分量的实现; 5. 采用邻接矩阵、邻接表、十字链表等多种结构存储来实现对图的存储. 1.2测试数据 1. 邻接矩阵测试数据:6 6 a b c d e f a b 2 a e 6 a d 5 b d 4 b c 1 b f 3 2. 邻接链表测试数据:7 8 a b c d e
8、 f g a b a e a c a f b g b d d g c f 3. 十字链表测试数据:4 5 3 2 2 5 4 3 99 3 4 66 2 概要设计 2.1 ADT描述 ADT Graph { 数据对象:V{具有相同特征的数据元素,即V顶点集} 数据关系:E={VR} VR={〈v,w〉|v,w∈V,〈v。w〉表示顶点v和顶点w之间的边;} 基本操作:初始化空图; 输入建立图; 广度优先遍历; 深度优先遍历; 最小生成树; }ADT G
9、raph 2.2程序模块结构 根据本系统对功能实现的要求,主要可以分为一下三个大的模块: 1. 邻接矩阵存储结构; 2. 邻接链表存储结构; 3. 十字链表存储结构; 其中每个模块又包涵其它相应的子功能模块. 则根据以上可以得到本系统的概要设计图 图的遍历与最小生成树 退出系统 十字链表存储结构 邻接链表存储结构 邻接矩阵存储结构 2.3 各功能模块(四号黑体) 2。3.1在邻接矩阵(AdjMWGraph)类中 void kruscal_arc(); //克鲁斯卡尔算法
10、AdjMWGraph(); //构造函数 void CreatG(int n,int e); //建立一个图的邻接矩阵 void DepthF(); //连通分量的实现 void BoradF(); //连通分量的实现 void PrintOut(); //输出图的信息 void Prim (); //普里姆算法 void kruscal_arc(); /
11、/克鲁斯卡算法 void DepthM(); //深度非递归优先遍历 void Borad(int v,int visited[]); //广度非递归优先遍历 void Depth(int v,int visited[]); //深度递归优先遍历 2.3.2在邻接链表( AdjTWGraph)类中 void Prim (); //普里姆算法 void CreatG(int n,int e); //建立一个图的邻接表 void kruscal_arc();
12、 //克鲁斯卡算法 void DepthF() //连通分量的实现 void BoradF() //连通分量的实现 void PrintOut(); //输出图的信息 void Borad(int v,int visited[]); //广度非递归优先遍历 void Depth(int v,int visited[]); //深度非递归优先遍历 void DepthM(int v,int visited[]);//深度递归优先遍历 2.3.3在十字
13、链表( Linkedmat )类中 void Creat(); //创建一个十字链表 void Show(); //输出显示十字链表 void zh(); //十字链表转换为邻接矩阵 void Depth(int v,int visited[]);//深度递归优先遍历 void Borad(int v,int visited[]);//广度非递归优先遍历 void DepthF(); //连通分量的实现 void BoradF();
14、 //连通分量的实现 void Prim (); //普里姆算法 void kruscal_arc(); //克鲁斯卡尔算法 3 详细设计 3。1结构体定义 struct Node { int row; int col; Node *down; Node *right; union { Node*next; ElemT
15、ype val; }; }; struct Edge{ int dest; ElemType weight; Edge *next; }; struct item { ElemType data; Edge *adj; }; struct MinSpanTree { ElemType begin,end; ElemType length; }; 3。2 初始化(四号黑体) 3.2。1邻接矩阵的初始化 AdjMWGraph() { for
16、 int i=0; i〈MaxVertices; i++ ) for ( int j=0; j〈MaxVertices; j++ ) { if( i==j ) Edge[i][j]=0; else Edge[i][j]=MaxWeight; } numE=0; numV=0; } 3.2.2邻接链表的初始化 AdjTWGraph::AdjTWGraph() { for(int i=0;i〈MaxVertices;i++) {
17、 Vertices[i].data=0;
Vertices[i].adj=NULL;
}
numV=0;
numE=0;
}
3。2。3十字链表的初始化
LinkeDmat()
{
*hm=null;
}
3。3 图的创建(四号黑体)
3。3.1创建图的邻接矩阵
void AdjMWGraph::CreatG(int n,int e)
{
int vi,vj,w,i;
numE=e; numV=n;
cout〈〈”\n 输入顶点的信息(整型):” ;
for (i=0; i 18、t<<”\n ”〈〈i+1<<”: ";
cin〉>Vertices[i];
}
for (i=0; i 19、"〈〈endl;
for(int i=0;i 20、ht=w;
q->next=NULL;
if(Vertices[vi-1].adj==NULL)Vertices[vi—1].adj=q;
else{
Edge *curr=Vertices[vi—1].adj,*pre=NULL;
while(curr!=NULL&&curr->dest 21、
}
else
{
q->next=pre->next;
pre—〉next=q;
}
}
Edge *p=new Edge;
p->dest=vi—1;
p->weight=w;
p->next=NULL;
if(Vertices[vj—1]。adj==NULL)Vertices[vj—1].adj=p;
else{
Edge *curr=Vertices[vj—1].adj,*pre=NULL;
while(curr!=NULL&&curr—>dest〈vi—1)
22、 {
pre=curr;
curr=curr—〉next;
}
if(pre==NULL)
{
p-〉next=Vertices[vj-1]。adj;
Vertices[vj—1]。adj=p;
}
else
{
p—〉next=pre-〉next;
pre-〉next=p;
}
}
}
}
3.3.3创建图的十字链表
void Linkedmat::Creat()
{
int m,n,r,c,v,s;
Node *p,*q,*h[10];
co 23、ut<〈"请输入您要创建的矩阵维数—〉”〈 24、
}
h[s]—>next=hm;
cout<〈endl〈〈”注意:"< 25、
cin>>r〉〉c>〉v;
p=new Node;
p—>row=r;
p-〉col=c;
p-〉val=v;
q=h[r];
while((q—>right!=h[r])&&(q—>right->col〈c))q=q-〉right;
p->right=q—〉right;
q-〉right=p;
q=h[c];
while((q-〉down!=h[c])&&(q->down—〉row〈r))q=q-〉down;
p—〉down=q-〉down;q—>down=p;
}
}
3。4 图的广度优先遍历(四号黑体 26、
3。4。1图的邻接矩阵的广度优先遍历
void AdjMWGraph::Borad(int v,int visited[])
{
SqQueue〈int>q;
cout< 27、axWeight&&visited[col]==0)
{
cout〈 28、es[v].data;
visited[v]=1;
Q.EnQueue(v);
while(!Q。IsEmpty())
{
v=Q。DeQueue();
p=Vertices[v]。adj;
while(p!=NULL)
{
vj=p-〉dest;
if(visited[vj]==0)
{
cout<<"\n顶点"< 29、>next;
}
}
cout〈 30、[col])Depth(col,visited);
}
}
3。5。2图的邻接矩阵的深度非递归优先遍历
void AdjMWGraph::DepthM()
{
int i,j,k,m;
cout〈<”\n 顶点”<<1〈〈"权值"〈〈Vertices[0]< 31、i]=0;
if(Edge[j][j]==0)
{
for(k=0;k 32、Edge[i][j]==0)
{
for(k=0;k〈numV;k++)
{
if(Edge[i][k]==0)
continue;
else
break;
}
if(k==numV)
break;
else
j++;
}
}
}
}
3.5.3图的邻接链表的深度递归优先遍历
void AdjTWGraph::DepthM(int v,int visited[])
{int vj;
Edge *p;
cout<< 33、"\n顶点"〈 34、ue(v);
while(!Q.IsEmpty())
{
v=Q.DeQueue();
cout<<"\n顶点"<〈v+1<<"权值"〈 35、 }
}
3.6 最小生成树的实现(四号黑体)
3.6.1普利姆算法
void AdjMWGraph::Prim ()
{
int n=numV,m,v,j,d;
MinSpanTree e, mintree[MaxVertices];
for (j=1; j 36、[j—1]。length=Edge[0][j];
}
for (int k=0; k〈n-1; k++)
{
int min=MaxWeight;
for (j=k; j〈n-1; j++)
if (mintree[j]。length〈min ) {min=mintree[j]。length; m=j;}
e=mintree[m]; mintree[m]=mintree[k]; mintree[k]=e;
v=mintree[k].end;
for ( 37、j=k+1; j 38、终点:"〈<
mintree[j].end〈〈” 权值:”〈 39、ee[k].length=Edge[i][j];
k++;
}
}
int x,y,m,n;
int buf,edf;
for(i=0;i 40、i;
}
}
buf=find(acrvisited,x);
edf=find(acrvisited,y);
mintree[n]。length=10000;
if(buf!=edf)
{
acrvisited[buf]=edf;
cout<<"(”< 41、for(int j=0;j 42、ces[i]〈〈" ”;
cout<<”\n 输出邻接矩阵 :” ;
for (i=0; i 43、 i=0;i〈numV;i++)
{
cout〈<”\n输出顶点编号信息,它的邻接点编号和边的权值:";
cout<〈" "〈dest<<" "<〈curr—〉weight;
curr=curr—>next;
}
cout〈 44、
cout〈〈endl<〈"以此十字链表存储的矩阵为:”<〈endl< 45、 else cout〈 46、矩阵建图
4 调试分析(小三黑体)
5 用户使用说明(小三黑体)
本系统是关于图的操作,可根据界面提示进行操作。
6 测试结果(小三黑体)
登录系统主界面,如下图:
图6。1 系统主菜单
选择功能1,进入第二菜单界面:
图 6.2 邻接矩阵存储结构
选择1,建立矩阵图:
图 6.3 邻接矩阵创建图
邻接矩阵显示:
图 5.4 矩阵显示图
返回第二菜单,选 47、择2,深度递归优先遍历:
图 6。5 深度递归优先遍历
选择3,广度非递归优先遍历:
图6。6 广度非递归优先遍历
选择4,最小生成树PRIM算法:
图6。7 最小生成树PRIM算法
选择5,最小生成树KRUSCAL算法
图6。8 最小生成树KRUSCAL算法
选择6,深度非递归优先遍历
图6。8 深度非递归优先遍历
返回主菜单,选择2,邻接链表存储结构的实现:
48、
图 6。9 邻接链表功能
选择功能1,如下:
图 6.10 图信息录入
选择2,深度非递归优先遍历
图 6。11 深度非递归优先遍历结果
选择3,广度非递归优先遍历
图 6.12 广度非递归优先遍历结果
选择4,广度优先遍历
图 6。13 广度递归优先遍历结果
返回主菜单,选择功能3:
49、 图 6。14 十字链表
选择1建立十字链表
图 6.15信息录入
选择2,显示矩阵
图 6.16 显示十字链表
结 论 (小三黑体,单独占页,居中)
通过一个学期对数据结构的系统学习和本次课程设计,加深了我对C++程序设计语言的认识,使得我对程序的开发过程有了更为深刻的理解。在实际编程过程中遇到过很多问题,迫使我去查阅各种资料,并且利用VC++6.0等软件开发工具以及一些建模工具解决了这些难题。通过这次的实验,我得出了一个结论,那就是 50、任何一个成功软件的背后都包含着检查和测试的艰辛,很多问题只有在实际运行中才能被发现,只有更加踏实工作和仔细查验才能让程序更加完美.
以上便是我对《数据结构课程设计》这门课的总结,在接下来的时间里,我要更加勤恳的投入到C++编程语言的学习实践中去,在打牢基础的前提下更加深入的学习.
致 谢 (小三黑体,单独占页,居中)
在本次课程设计过程中,首先感谢陈红红老师对我的细心辅导和帮助。感谢学校给我们这次机会让我们独自解决一系列问题,感谢唐建梅老师数据结构课堂上的仔细讲解,在陈老师的指






