算法的实现数据结构与算法课程设计报告.docx
- 文档编号:24491576
- 上传时间:2023-05-28
- 格式:DOCX
- 页数:21
- 大小:91.04KB
算法的实现数据结构与算法课程设计报告.docx
《算法的实现数据结构与算法课程设计报告.docx》由会员分享,可在线阅读,更多相关《算法的实现数据结构与算法课程设计报告.docx(21页珍藏版)》请在冰豆网上搜索。
算法的实现数据结构与算法课程设计报告
合肥学院
计算机科学与技术系
课程设计报告
课
2009
〜2010学年第2学期
程
数据结构与算法
课程设计名称
Dijkstra算法的实现
学生
姓
名
张睿辰
学
号
0804012044
专业
班
级
08计科⑵班
指导
教
师
王昆仑张贯虹
2010年
6月
Dijkstra算法的实现
一、问题分析与任务定义
1、课程设计题目:
1.1题目:
对任意图,选择合适的数据结构表示图,在此基础上实现求解最短路径
的Dijkstra算法
1.2要求:
设计合理的数据结构存储图,简单有效的实现Dijkstra算法。
1.3具体任务:
建立图的存储模块,建立图的输出模块,在建图后从单源点开始求最短路径,并显示出来!
2、原始数据的输入格式:
2.1建图模块:
2.1.1数字
2.2.2数字+空格+数字+空格+数字+回车
2.3显示模块:
回车
3、实现功能:
3.1建立有向图
3.2显示存储的有向图
3.3显示从顶点到其他各顶点的最短路径
4、测试用例:
4.1正确数据:
a)顶点:
3;边值信息:
016;024;125;206;000;
b)顶点:
0;边值信息:
000;
输出结果:
a)v0到v1的最短路径是6,v0到v2的最短路径是4
b)没有最短路径
4.2错误数据:
a)顶点:
a
b)顶点:
2;边值信息:
036;044;135;000;
c)顶点:
3;边值信息:
01a;
输出结果:
边值错误,请从新输入
5、问题分析:
实现本程序要解决以下几个问题:
5.1如何存储一个有向图。
5.2如何在界面中输出该有向图。
5.3如何定义起始源点。
5.4如何选择出最短路径。
5.5找到的最短路径如何输出。
二、数据结构的选择和概要设计
1、数据结构的选择:
在图的结构中,任意两个顶点之间都可能存在关系,比线性表和树要复杂。
由于不存在严格的前后顺序,因而不能采用简单的数组来存储图;另一方面,如果采用链表,由于图中各顶点的度数不尽相同,最小度数和最大度数可能相差很大,如果按最大度数的
顶点来设计链表的指针域,则会浪费很多存储单元,反之,如果按照各个顶点设计不同的链表结点,则会给操作带来很大的困难。
在此我选用邻接矩阵的存储结构。
采用邻接矩阵存储,很容易判断图中两个顶点是否相连,也容易求出各个顶点的度。
不过任何事情都不是完美的,采用邻接矩阵存储图时,测试其边的数目,必须检查边二维数组的所有元素,时间复杂度为0(n2),这对于
顶点很多而边较少的图(稀疏图)是非常不合算的。
以邻接矩阵存储有向图,如图1中有向图
G所示,其邻接矩阵为图
2cost。
0
50
10
OO
45
OO
OO
0
15
50
10
OO
20
OO
0
15
OO
OO
OO
20
OO
0
35
OO
OO
OO
OO
30
0
OO
OO
OO
OO
3
OO
0
intcost[n][n];
2、概要设计
2.1对于最短路径问题:
最短路径是在实际应用中非常有用的工具,我们常见的两种最短路径是:
(1)从某源点到其余各顶点之间的最短路径。
(2)每一段顶点之间的最短路径
在这里我们解决第一类问题。
2.2Dijkstra算法用于求最短路径:
Dijkstra算法是按路径长度递增的次序逐步产生源点到其他顶点间的最短路径。
算法建立一个顶点集合S,初始时该集合只有源点V0,然后逐步将已求得最短路径
的顶点加入到集合中,直到全部顶点都在集合S中,算法结束。
2..3Dijkstra算法思想
设cost[i,j]=0,S为已经求得最短路径的顶点集合,distance[i]数组的每个元素表
示当前状态下源点V0到Vi的最短路径。
算法如下:
1)初始化:
S={V0},distance[i]=cost[0,i]。
2)选择一个终点Vj,满足distance[j]=MIN{distance[i]|Vi€V-S}。
3)把Vj加入到S中。
4)修改distanee数组元素,修改逻辑为对于所有不在S中的顶点Vi.
if(distance[j]+cost[i,j] 5)重复操作2)、3)、4),直到全部顶点加入到S中。 2.4实现流程 在任意图中实现求最短路径问题,第一步是要能成功的在内存中输入图的信息, 图的信息有两个,一是顶点个数,二是每两点之间的权值信息。 当建立图之后,对图进行遍历才能使用Dijkstra算法求出最短路径;在完成了图的建立之后,用Dijkstra算法的思想,从单源点开始,求出到各个顶点的最短路径,并能够实现显示功能。 程序流程图: 开始 输入顶点与边值信息 Dijkstra 算法 求最短路径 结束 Dijkstra算法流程图: 三、详细设计和编码 3.1邻接矩阵的定义: 我们定义全局变量cost[][],dist[]数组,方便在各子程序中的调用,加快了程序的运行速度。 intcost[MAX][MAX]; intdist[MAX]; intn; cost二维数组用于存放邻接矩阵,每个位置代表的值为图中的权值,其余用无穷大999表示。 dist为辅助数组,图中每个顶点对应该数组中的一个元素,这个元素存放当前源点到该顶点的最短路径。 此时的路径指示当前结果,并不一定是最终的最短路径。 随着集合S的变化,其他顶点不断地加入到集合中,可能以这些新加入的顶点为“桥梁”产生比以前路径更短的路径,dist数组元素的值是动态变化的。 n是指图中的顶点数目。 3.2结点结构体的定义: struct { intnum; intpnode[MAX]; }path[MAX]; 整型变量num是用来记录求V0到每个顶点的最短路径时所经过的顶点的数目。 数组pnode用来存放求V0到每个顶点的最短路径时所经过的顶点,初始为V0。 结构体数组path为从V0到各顶点的最短路径。 3.3创建带权有向图 初始化邻接矩阵cost中的值为无穷大,即任意两个顶点之间不存在路径。 首先输入该有向 图的顶点数n,然后依次输入各个顶点及边长(输入的顶点的序号应该小于顶点的数目)。 输 入000结束。 定义变量contin,标志输入是否结束。 若contin=1,输入继续,若contin=0,输入完成。 代码: voidcreatgraph()//创建带权有向图 { inti,j,s,e,len,contin=1; printf("\n请输入顶点个数: "); scanf("%d",&n); for(i=0;i { for(j=0;j cost[i][j]=up; cost[j][i]=up;//初始化所有顶点间的边值均为无穷大} cost[i][i]=0;//每个顶点到自己的边值为0 } printf("输入各边,以0,0,0表示结束: \n"); i=1;//标志边的数目 while(contin==1) { printf("\t第%d条边->顶点,顶点,边长: ",i); scanf("%d%d%d",&s,&e,&len); if(s==0&&e==0&&len==0) contin=0; elseif(s>=0&&s cost[s][e]=len; i++; } else printf("\t\t边值错误,重复输入! \n"); } display(n);//输出所建数组 getchar(); } 3.4邻接矩阵的显示 在图的邻接矩阵显示中,分别利用for循环输出了矩阵的行列标,使矩阵很明了。 代码: voiddisplay(intn1) { inti,j; **\n"); ******************************** for(i=0;i printf("%d",i);//利用for循环输出邻接矩阵的行标 printf("\n"); for(i=0;i { printf("%d",i);//利用for循环输出邻接矩阵的列标 for(j=0;j printf("\t%3d<%d,%d>",cost[i][j],i,j); printf("\n"); } } 3.5Dijkstra求最短路径的实现 设图以邻接矩阵cost存储,矩阵中各元素的值为各边的权值。 顶点间无边时其对应权值用无穷大表示。 从顶点V0到其它各顶点间的最短路径的具体步骤如下: a)变量定义: 定义整型数组S[],这是一个顶点集合,初始时该集合只有源点vO,然后逐步将以求 得最短路径的顶点加入到该集合中,直到全部顶点都在集合S中,算法结束。 定义 两个整型变量dis、mindis均用来标志图中最短的那一条路径。 b)初始化: 初始化dist数组的值即为cost数组中存放的权值。 dist[i]=cost[v0][i] vO顶点。 path[i].pnode[O]=vOpath[i].num=O; s[i]=O; 初始化求到每个顶点的最短路径时都经过初始化记录经过的顶点数都为O。 初始化顶点集合s为空,即还未开始。 c)源点的选择: 将vO顶点加入到顶点集合s中。 s[v0]=1 d)利用for循环选择一个终点Vj,使其满足VO到Vj距离最短,同时将Vj加入集合S中。 e)根据j顶点调整当前的最短路径,若满足dist[i]>dist[j]+cost[j][i],则修改dist[i]的值。 同时VO到Vi的最短路径中经过的顶点数加1,即path[i].num++;并将经过的顶点存入数组pnode即path[i].pnode[path[i].num]=j f)此时一趟求最短路径完毕,将终点V1添加到路径中。 g)循环执行d),e),f)操作,直到全部顶点加入到S中。 代码: voidshortdjs()//求最短路径{ints[MAX]; intmindis,dis,i,j,vO=O,u=O;//mindis标志图中最短的那一条路径for(i=O;i { dist[i]=cost[vO][i]; path[i].pnode[O]=vO; path[i].num=O; s[i]=O; } s[vO]=1; for(i=1;i mindis=up; for(j=1;j if(s[j]==O&&dist[j] { u=j; mindis=dist[j]; } s[u]=1; for(j=1;j if(s[j]==O) { dis=dist[u]+cost[u][j]; if(dist[j]>dis) { dist[j]=dis; path[j].num++; path[j].pnode[path[j].num]=u; } } path[i].num++; path[i].pnode[path[i].num]=i; } } 3.6最短路径的输出 这段函数主要运用for循环,依次输出V0到Vi的最短长度与最短路径。 voiddispath()//输出最短路径 { inti,j; printf("\n从V0到各顶点的最短路径长度如下: \n"); printf("(起点->终点)最短长度最短路径\n"); printf("\n"); for(i=1;i { printf("(V0->V%d): ",i); if(dist[i] printf("\t%d\t<",dist[i]); else printf("\t%\t<");〃显示无穷大 for(j=0;j printf("V%d->",path[i].pnode[j]); printf("V%d>\n",path[i].pnode[path[i].num]);} } } 四、上机调试 4.1记录调试过程中遇到的错误和问题 a)当输入格式不符合程序要求时,会提示错误输入,但会出现死循环,可以定义一个标志量contin,当要停止的时候,命令contin=0,循环结束; b) 999代 并对程 当两顶点间没有路径时,权值为无穷大,但在本程序中只能用一个具体的数字替抽象的无穷大。 c)在程序的调试过程可暂时多加一些输出语句以便及时查看一下中间运行情况,序规格说明作调整和改动。 4.2算法的时间和空间性能分析 4.2.1时间复杂度 对于n个顶点的有向图,求一个顶点到其他顶点的最短路径的时间为O(n),调整最 短路径的循环共执行n-1次,是二层循环,所以,时间复杂度是O(n2)。 4.2.2空间复杂度 采用邻接矩阵存储有向图,应处理每两个顶点之间的关系,所以空间复杂度为O(n2)。 4.3算法设计、调试的经验和体会 Dijkstra算法在上课的时候曾作为重点讲过,所以在做查找最短路径的算法时很流畅,但是在输出最短路径的时候遇到了很大的阻力。 因为在定义结点时,使用的是结构体数组,所以当处理V0到每个结点的最短路径时,导致无法具体记录经过的顶点数,只能记录源点、终点前一顶点以及终点。 所以本程序在输出最短路径时有较大的瑕疵,还需进一步修改。 五、测试结果 测试1: 验证当两点间不存在路径时,程序是否正确。 当顶点间无路径时,最短路径为无穷大。 程序正确。 测试2: 输入一组正确的数据,测试程序的正确性。 通过测试,验证了程序是正确的。 测试3: 测试当输入错误的时,程序是否正确。 当输入错误时,提示重新输入,程序正确。 六、用户使用说明 该程序可应用在出行指南中,用0~20表示出行地点,输入路径,得出最优出行路线。 用户操作方法如下: 1、输入顶点个数: 最大不超过20,请输入罗马数字,若输入其他符号,会显示警告; 2、以“数字数字数字”的格式输入图的信息,输入的数字0即表示源点,前两个数字应小于顶点个数,最后一个数字应小于999。 当输入“000”时,输入完成; 3、在输入完成后,屏幕显示邻接矩阵与最短路径。 七、参考文献 1、王昆仑,李红编著.数据结构与算法.北京: 中国铁道出版社,2007. 2、严蔚敏,陈文博编著.数据结构及算法教程.北京: 清华大学出版社,2001 八、附录 #include #include #include #defineMAX20 //最多顶点个数 #defineup999 //定义一个无穷大的值 intcost[MAX][MAX]; //cost为带权邻接矩阵 intdist[MAX],n; //dist为辅助数组,每个顶点对应该数组中的一个元素,这个元素存放当前源点到该顶点的最短路径。 struct { intnum; //记录求v0到每个顶点的最短路径时所经过的顶点的数目 intpnode[MAX];初始为v0 //用来存放求v0到每个顶点的最短路径时所经过的顶点, }path[MAX]; //path为从V0到各顶点的最短路径 voiddisplay(intn1) { inti,j; **\n"); ******************************** for(i=0;i printf("%d ",i);//利用for循环输出邻接矩阵的行标 printf("\n"); for(i=0;i { printf("%d",i);//利用for循环输出邻接矩阵的列标 for(j=0;j printf("\t%3d<%d,%d>",cost[i][j],i,j); printf("\n"); } }//输出所建图的邻接矩阵 voidcreatgraph()//创建带权有向图 { inti,j,s,e,len,contin=1;//contin为标志变量,当contin=1时表示输入正确,当contin=0时,表示输入结束 printf("\n请输入顶点个数: "); scanf("%d",&n); for(i=0;i { for(j=0;j cost[i][j]=up; cost[j][i]=up;//初始化所有顶点间的边值均为无穷大 } cost[i][i]=0;//每个顶点到自己的边值为0 } printf("输入各边,以0,0,0表示结束: \n"); i=1;//标志边的数目 while(contin==1) { printf("\t第%d条边->顶点,顶点,边长: ",i); scanf("%d%d%d",&s,&e,&len); if(s==0&&e==0&&len==0) contin=0; elseif(s>=0&&s { cost[s][e]=len; i++; } else printf("\t\t边值错误,重复输入! \n"); } display(n);//输出所建数组 getchar(); } voidshortdjs()//求最短路径 { ints[MAX];//顶点集合,初始时该集合只有源点vO,然后逐步将以求得最短路径 的顶点加入到该集合中,直到全部顶点都在集合S中,算法结束 intmindis,dis,i,j,vO=O,u=O;//mindis标志图中最短的那一条路径for(i=O;i { dist[i]=cost[v0][i];//初始化dist[]数组,顶点vOv1v2是与012——对应的path[i].pnode[O]=vO;//初始化求到每个顶点的最短路径时都经过vO顶点path[i].num=0;//初始化记录经过的顶点数都为0 s[i]=0;//顶点集合s为空,即还未开始 } s[vO]=1;//vo定点加入到s中,等于1表示已进入该集合 for(i=1;i { mindis=up;//记录最短路径 for(j=1;j if(s[j]==0&&dist[j] { u=j;//找到离上一个顶点距离最短的结点 mindis=dist[j];//将v0到此结点的距离赋值给mindis } s[u]=1;//u定点加入到s中,u记录的是距v0最短的顶点 for(j=1;j if(s[j]==0) { dis=dist[u]+cost[u][j];〃计算经过u结点,v0到j这个结点的距离 if(dist[j]>dis)//如果v0直接到j的距离,大于经过u结点,v0到j结点的距离 { dist[j]=dis;//最短距离记录为dist path[j].num++;//记录经过的顶点数 path[j].pnode[path[j].num]=u;//记录经过的结点 } } path[i].num++;//将终点i添加到路径中 path[i].pnode[path[i].num]=i; } } voiddispath()//输出最短路径 { //system("cls"); inti,j; printf("\n从V0到各顶点的最短路径长度如下: \n"); printf("(起点->终点)最短长度最短路径\n"); printf("\n"); for(i=1;i printf("(V0->V%d): ",i); if(dist[i] \t<",dist[i]); printf("\t %d else printf("\t OG \t<");//显示无穷大 for(j=0;j printf("V%d->",path[i].pnode[j]); printf("V%d>\n",path[i].pnode[path[i].num]);//只输出源点、终点、终点的前一顶点。 } } voidmain() { inti,p=3; for(i=0;i printf( printf("************ ************\n"); 欢迎使用迪杰斯特拉算法实现在任意图中求最短路径! printf( H********************** **\n",i); printf( H********************** **\n",i); intj,q=3; for(j=0;j H************************************************************************ creatgraph(); shortdjs();dispath(); getchar(); getchar();
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 实现 数据结构 课程设计 报告