算法与数据结构课程设计报告文档格式.docx
《算法与数据结构课程设计报告文档格式.docx》由会员分享,可在线阅读,更多相关《算法与数据结构课程设计报告文档格式.docx(30页珍藏版)》请在冰豆网上搜索。
![算法与数据结构课程设计报告文档格式.docx](https://file1.bdocx.com/fileroot1/2023-1/27/5cddaeeb-4b8b-4adc-9b7c-2573df42fd9f/5cddaeeb-4b8b-4adc-9b7c-2573df42fd9f1.gif)
三、需求分析:
按照需求,需要设计四种图、两种存储结构、创建四种图的个两种存储结构的操作(8个)、其他基本操作、多级菜单显示,图的操作有用到了线性表、栈和队列的基本操作。
在老师给出了多级菜单现实的代码后,我们需要做的只是将函数写入其中。
四、总体设计:
我用的软件是VisualC++6.0。
将不同的操作分在了不同的包里面。
如右图所示。
Typedef.h包里面是所有的相关结构定义;
UDG_Operation.h包里面是有关于无向图的有关操作;
UDN_Operation.h包里面是有关于无向网的有关操作;
DG_Operation.h包里面是有关于有向图的有关操作;
DN_Operation.h包里面是有关于有向网的有关操作;
Queue_Operation.h包里面是有关队列的有关操作;
Stack_Operation.h包里面是顺序栈的有关操作。
包的引用很有规范,如下:
#include"
stdafx.h"
iostream"
#include<
algorithm>
stdlib.h"
stdio.h>
stdlib.h>
malloc.h"
usingnamespacestd;
intvisited[20];
Typedef.h"
Queue_Operation.h"
Stack_Operation.h"
UDG_Operation.h"
UDN_Operation.h"
DG_Operation.h"
DN_Operation.h"
菜单由于老师已经给出,主要就是将函数带上参数写入代码。
在菜单选择后触发函数,得出结果。
函数总结:
创建无向图的邻接矩阵:
CreatUDG_M(MG);
打印无向图的邻接矩阵:
dispgraph_MG(MG);
创建无向图的邻接表:
CreatUDG_ALG(ALG);
打印无向图的邻接表:
dispgraph_G(ALG);
无向图的深度优先遍历:
DFSTraverse(ALG);
无向图的广度优先遍历:
BFSTraverse(ALG);
创建无向网的邻接矩阵:
CreatUDN_M(MN);
打印无向网的邻接矩阵:
dispgraph_MN(MN);
创建无向网的邻接表:
CreatUDN_ALG(ALN);
打印无向网图的邻接表:
dispgraph_N(ALN);
Prim算法求最小生成树:
MiniSpanTree(MN,1);
kraskal算法求最小生成树:
kruskal();
创建有向图的邻接矩阵:
CreatDG_M(MG);
打印有向图的邻接矩阵:
创建有向图的邻接表:
CreatDG_ALG(ALG);
打印有向图的邻接表:
dispgraph_DG_G(ALG);
拓扑排序:
TopologicalSort(ALG);
创建有向网的邻接矩阵:
CreatDN_M(MN);
打印有向网的邻接矩阵:
创建有向网的邻接表:
CreatDN_ALG(ALN);
打印有向网的邻接表:
dispgraph_DN_G(ALN);
求关键路径:
CriticalPath(ALN);
求单源顶点最短路径:
ShorttestPath_DIJ(MN,1);
求每对顶点间最短路径:
ShorttestPath_FLOYD(MN);
大体设计就是这么一个流程。
还有一些有关于循环队列和顺序栈的操作,这里就不一一列出了。
五、详细设计与实现(含代码和实现界面):
5.0.储存所有定义和预处理的包(typedef.h)
5.0.1.预处理:
#defineMAXVEX30//最大结点的个数
#defineMAXCOST1000//最大权值
#defineSTACKINCREMENT10//栈的增量
typedefcharVertexType;
//结点信息类型
5.0.2.图的邻接矩阵存储结构:
typedefstruct{
VertexTypevexs[MAXVEX];
//顶点信息
intarcs[MAXVEX][MAXVEX];
intvexnum,arcnum;
//顶点数、边数
}MGraph;
5.0.3.图的邻接表存储结构:
typedefstructarcnode{
intadjvex;
//邻接点序号
intw;
//边或狐上的权
structarcnode*next;
//指向下一条弧的指针
}ArcNode;
typedefstructvnode{
VertexTypedata;
//顶点信息
intindegree;
//该点的度
ArcNode*firstarc;
//指向下一个边结点
}Vnode,AdjList[MAXVEX];
AdjListvertices;
//图的当前顶点数和弧数
}ALGraph;
5.0.4.循环队列和栈的顺序存储表示
a.在处理无向图的广度优先遍历用到了循环队列极其简单操作。
//————————栈的顺序存储表示————————
int*base;
int*top;
intStacksize;
}SqStack;
//————————队列定义————————
typedefstructSqQueue{
intfront;
intrear;
}SqQueue;
5.0.5.多级菜单展示
主菜单:
次级菜单展示:
5.1.无向图的基本操作及应用(UDG_Operation.h)
5.1.1.创建无向图的邻接矩阵
用一个二维数组实现的。
测试用如右图的无向图。
测试结果:
5.1.2.创建无向图的邻接表
主要运用指针,运用链式分配存取空间。
5.1.3.无向图的深度遍历
无向图的深度优先遍历我采取的是用邻接表的方式。
从图中的某个顶点出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历,直至途中所有和v有路径相同的顶点都被访问到,若此时还有顶点未被访问,则另选图中一个未曾被访问的顶点做起始点,重复上述过程,直到所有顶点被访问完。
5.1.4无向图的广度优先遍历
广度优先遍历也是利用邻接表,从顶点v出发访问v后依次访问v的各个未曾访问的邻接点,直到所有的邻接点被访问。
若此时图中尚有顶点未被访问,则选择途中另一个未曾被访问的结点作为起始点重复上述过程。
5.2.无向网的基本操作及应用(UDN_Operation.h)
5.2.1.创建无向网的邻接矩阵
和无向图的几乎差不多,只是当两个顶点之间存在边时,存的是边的权值,不存在边时用-1表示。
5.2.2.创建无向图的邻接表
与无向图的几乎一样,只是把权值存入其中。
5.2.3.prim算法求最小生成树
主要利用无向网邻接矩阵的存取方式操作的,还需要用到一个标志数组。
5.2.4.kraskal算法求最小生成树
主要是如何判断两个顶点是否属于同一分支,这里用一个数组记录。
5.3.1.创建有向图的邻接矩阵
有向图的邻接矩阵和无向图的邻接矩阵实现过程一样,只是存的弧是有顺序的。
5.3.2.创建有向图的邻接表
有向图的邻接表的实现过程和无向图的过程几乎一样,只是存取弧是有顺序。
5.3.3.拓扑排序
有向图的拓扑排序主要用到栈,采用的是有向图的邻接表的存取方法。
5.4.1.创建有向网的邻接矩阵
和无向网的邻接矩阵思想一样,其中两顶点有边时,存入他们的权值,弧也是有方向的。
5.4.2.创建有向网的邻接表
实现过程与无向网的邻接表的实现过程一样,只是这里两点的边有方向。
5.4.3.求关键路径
主要是求取每个活动的最早和最迟发生时间,这里用到拓扑排序的思想求最早发生时间和逆拓扑排序的思想求最迟发生时间。
5.4.4.求单源顶点最短路径的问题
运用了迪杰斯特拉算法,用了网的邻接矩阵存取方式。
所求的无向网如右图。
5.4.5.求每对顶点间最短路径的问题
采用了弗洛依德算法,采用的也是有向网的邻接矩阵的存取方式。
六、课程设计小结:
1.难点与收获:
这次是我第一次用VisualStudio2008编写小程序,以前只是用它来做过一些动态网页,所以一开始使用的不是很熟悉,比如:
包的导入顺序这个问题也是让我找了半天——先用到的必需放在前面。
后来的编写过程也不是很顺利。
书上都是一些伪码,使我不得不再到网上多看一些代码来做参考,但是也还是会遇到十分不好解决的问题。
有一些算法很是复杂,参考再多也不能看懂。
一般都还是得再去请教他人。
代码做出来后,有的问题不是什么简单的语法问题,而是逻辑问题。
这种是最难找的,不过我还是想起了以前老师教的一种方法:
设置断点,新加入做参考的变量一步一步的调试。
用这个方法着实解决了一些变量的问题,如未初始化、没有加&
改变数据。
通过这一次的课设,我深深的体会到了编写代码所必须的性格:
耐心、细心。
在遇到问题是一定要静下心来,不要急躁,细心的查看代码,耐心的调试。
在这些过程当中,确实会感到急躁,但是一旦在我们解决问题后,总是会有一种成就感油然而生。
我想这应该是学习计算机的人们都会有的感觉吧。
在今后的学习中我定将继续努力,继续享受这份学习计算机编程的乐趣。
2.可以改进的地方
我知道我程序写的不完美,有许多可改进的地方,但是在目前我还不知道具体需要从哪里下手改进,如果我知道我一定会用我觉得好的方法去编写。
不得不说,我现在的水平和理解能力有限,有待提高的地方还有很多。
学习编程的路程是艰辛的,我现在自己独立编写代码,独立思考的能力还是太有限了,代码参考的成分居多,希望以后我可以更加独立的去完成任务。
七、部分重要代码:
UDG_Operation.h无向图的深度优先遍历和广度优先遍历。
//无向图的深度优先遍历
voidDFS(ALGraphALG,intv){
ArcNode*p;
intv1=ALG.vertices[v].data;
cout<
<
v1<
"
"
;
visited[v]=1;
p=ALG.vertices[v].firstarc;
while(p!
=NULL){
if(visited[p->
adjvex]==0)
DFS(ALG,p->
adjvex);
p=p->
next;
}
}
voidDFSTraverse(ALGraphALG){
intv;
for(v=1;
v<
=ALG.vexnum;
v++){
visited[v]=0;
该图的深度优先遍历结果:
if(visited[v]==0)
DFS(ALG,v);
\n"
//无向图的广度优先遍历
voidBFS(ALGraphALG,intv){
SqQueue*Q;
Q=(SqQueue*)malloc(sizeof(SqQueue));
Q->
front=Q->
rear=0;
ALG.vertices[v].data<
EnQueue(*Q,v);
while(!
QueueEmpty(Q)){
DeQueue(*Q,v);
p=ALG.vertices[v].firstarc;
while(p!
=0){
if(visited[p->
adjvex]==0){
v=p->
adjvex;
cout<
visited[v]=1;
EnQueue(*Q,v);
}
p=p->
}
voidBFSTraverse(ALGraphALG){
v++)
该图的广度优先遍历结果:
BFS(ALG,v);
UDN_Operation.hprim算法和kruskal算法求最小生成树
//prim算法求最小生成树
voidMiniSpanTree(MGraphG,intu){
inti,i1;
intj,j1;
intk=INT_MAX;
j1=u;
struct{
intlowcost;
//各边上当前最小权值
intadjvex;
//权值依附的顶点的序号
}closedge[MAXVEX];
for(j=1;
j<
=G.vexnum;
j++){//初始化辅助数组
if(j!
=u){
closedge[j].lowcost=G.arcs[u][j];
if(G.arcs[u][j]!
=-1){
closedge[j].adjvex=u;
else{
closedge[j].adjvex=0;
else{
closedge[j].lowcost=0;
}
for(i=1;
i<
=G.vexnum-1;
i++){
k=INT_MAX;
for(i1=1;
i1<
i1++){//找到当前最小的边
if(i1!
=u&
&
closedge[i1].lowcost!
=-1&
if(closedge[i1].lowcost<
k){
k=closedge[i1].lowcost;
u=closedge[i1].adjvex;
j1=i1;
}
cout<
G.vexs[u]<
-->
G.vexs[j1]<
endl;
closedge[j1].lowcost=0;
for(j=1;
j++){//添加新的结点
if(closedge[j].lowcost!
if(G.arcs[j1][j]!
G.arcs[j1][j]<
closedge[j].lowcost&
closedge[j].lowcost!
=0){
closedge[j].lowcost=G.arcs[j1][j];
closedge[j].adjvex=j1;
closedge[j].lowcost=G.arcs[j1][j];
closedge[j].adjvex=j1;
//kruskal算法求最小生成树
intr[MAXVEX+1];
//记录点的顺序
intp[MAXVEX+1];
//判断是结点否属于同一分支数组
intcho[MAXVEX*(MAXVEX-1)/2+1]={0};
//记录边的顺序
intn;
//顶点数
intm;
//边数
structedge{
intu;
//起始点编号
//终点编号
//权值
}e[MAXVEX*(MAXVEX-1)/2+1];
voidInit(){
inti;
=MAXVEX;
p[i]=i;
r[i]=0;
boolcmp(edgea,edgeb){//判断两条边权值的大小
returna.w<
b.w;
intFind(intt){//找到编号为t的邻接点
if(p[t]!
=t){
p[t]=Find(p[t]);
returnp[t];
voidUnion(inta,intb){//判断是否属于同一分支
intx,y;
x=Find(a);
y=Find(b);
if(r[x]>
r[y]){
r[y]=x;
else{
p[x]=y;
if(r[x]==r[y])
r[y]++;
voidkruskal(){
请输入顶点数和边数:
cin>
>
n>
m;
inti,j;
=m;
请输入第"
条边的起点序号、终点序号和权值:
cin>
e[i].u>
e[i].v>
e[i].w;
Init();
sort(e+1,e+m+1,cmp);
intcnt=0;
if(Find(e[i].u)!
=Find(e[i].v)){
cnt++;
Union(e[i].u,e[i].v);
cho[++cho[0]]=i;
if(cnt==n-1)
break;
=cho[0];
j++){
e[cho[j]].u<
->
e[cho[j]].v<
DG_Operation.h拓扑排序
voidTopologicalSort(ALGraphALG){
intk;
intcount=0;
ArcNode*p=(ArcNode*)malloc(sizeof(ArcNode));
SqStackS;
InitStack(S);
=ALG.vexnum;
if(ALG.vertices[i].indegree==0)
Push(S,i);
while(S.top!
=S.base){
Pop(S,i);
ALG.vertices[i].data<
++count;
for(p=ALG.vertices[i].firstarc;
p!
=NULL;
p=p->
next){
k=p->
adjvex;
ALG.vertices[k].indegree--;
if(ALG.vertices[k].indegree==0){
Push(S,k);
if(count<
ALG.vexnum){
该有向图中存在环"
return;
DN_Operation.h关键路径,单源顶点最短路径问题每对顶点间最短路径问题
//求关键路径
intve[MAXVEX];
intvl[MAXVEX];
//求最早发生时间
intTopologicalOrder(ALGraphALN,SqStack&
T){
=ALN.vexnum;
if(ALN.vertices[i].indegree==0)
Push(T,i);
for(p=ALN.vertices[i].firstarc;
p;
next){
ALN.vertices[k].indegree--;
if(ALN.vertices[k].indegree==0)
if(ve[i]+p->
w>
ve[k])
ve[k]=ve[i]+p->
w;
if