数据结构课程设计报告关键路径docx.docx
《数据结构课程设计报告关键路径docx.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告关键路径docx.docx(26页珍藏版)》请在冰豆网上搜索。
数据结构课程设计报告关键路径docx
XIANTECHNOLOGICALUNIVERSITY
《算法与数据结构》课程设计
题目:
关键路径
院、系:
学科专业:
姓名:
学号:
指导教师:
数据结构课程设计报告
关键路径是我们估算某些工程非常有用,是一种非常重要的估算一项工程所需的最短时间的依据。
本文对如何求一个工程的关键路径做了详细的说明,包括需求分析、概要设计、详细设计、测试与分析、总结、源程序清单。
首先,做了需求分析,解释了什么是关键路径,并指出它在估算工程中的重要作用。
然后给出求关键路径的概要设计,包括程序中用到的所有抽象数据类型的定义,主程序的流程以及各程序模块之间的层次(调用)关系。
在概要设计的基础上,又给出了详细的算法设计,实现概要设计中定义的所有函数,对每个函数写出核心算法,并画出了流程图。
然后对编码进行了测试与分析(并在最后附上C语言编写的程序代码)。
最后对整个设计过程进行了总结,,
关键词:
关键路径;抽象数据类型;程序模块;核心算法;流程图
1
3
3
1.2研究意义3
1.3结构安排3
2需求分析5
2.1问题描述5
2.2基本要求5
2.3目的5
3概要设计7
3.1算法分析7
3.2算法步骤7
3.3数据结构8
3.3.1数据结构8
3.3.2程序模块8
3.3.3各模块间的调用关系9
4详细设计10
4.1主要函数的核心代码10
4.2程序流程图10
5测试11
6总结16
参考文献18
附录:
原程序清单佃
绪论
1绪论
1.1前言:
我们通常把计划、施工过程、生产流程、程序流程等都当成一个工程。
工程通常分为若干个称为“活动”的子工程。
完成了这些“活动”,这个工程就可以完成了。
我们通常用AOE网来表示工程。
AOE网是一个带权的有向无环图,其中,顶点表示事件(EVENT,弧表示活动,权表示活动持续的时间。
AOE网可以用来估算工程的完成时间。
他可以使人们了解:
1.研究某个工程至少需要多少时间?
2.哪些活动是影响工程进度的关键?
由于AOE网中的有些活动可以并行进行,从开始点到各个顶点,以致从开始点到完成点的有向路径可能不止一条,这些路径的长度也可能不同。
完成不同路径的活动所需的时间虽然不同,但只有各条路径上所有活动都完成了,这个工程才算完成。
因此,完成工程所需的最短时间是从开始点到完成点的最长路径的长度,即在这条路径上的所有活动的持续时间之和.这条路径长度就叫做关键路径(CriticalPath)。
1.2研究意义:
关键路径可以很方便的让我们估算出某个工程最短的时间开销,以及这个工程中哪些活动,即哪些项目是主要的,是影响工程进度的关键,从而让我们对工程的实施作出更好的时间安排,并且可以分清主次,抓住核心工程,做到有的放矢。
总的来说,正因为关键路径可以帮助我们对工程进行非常有必要的估算,让我们得以看清全局,作出更为优化的安排,所以可见关键路径的求出对一项工程而言是非常必要的。
这亦是本次对关键路径求法的研究意义所在。
1.3结构安排:
第一章绪论介绍了研究背景以及研究意义。
第二章需求分析介绍了问题描述以及基本要求,和这次课程设计所需达到的目的。
第三章概要设计主要介绍了求关键路径的算法分析,算法步骤,和数据结构,其中数
据结构包括了基本的抽象数据结构,所要用到的函数模块,以及各模块之间的调用关系第四章详细设计介绍了主要函数及其核心代码,以及程序流程图。
第五章对程序代码进行了测试。
第六章对这次数据结构课程设计进行了总结。
参考文献。
附录:
原程序清单
需求分析
2需求分析
2.1问题描述:
(1)选取建图的一种算法建立图,有邻接矩阵,邻接表,十字链表,邻接多重表等多种方法,要选取一种适当的方法建立图,才能提高算法效率,降低时间复杂度和空间复杂度。
(2)两个相邻顶点与它们之间的边表示活动,边上的数字表示活动延续的时间。
对于给出的事件AOE网络,要求求出从起点到终点的所有路径,经分析、比较后找出长读最大的路径,从而得出求关键路径的算法,并给出计算机上机实现的源程序。
完成不同路径的活动所需的时间虽然不同,但只有各条路径上所有活动都完成了,这个工程才算完成。
具体要解决的问题有如下四个:
1)将项目中的各项活动视为有一个时间属性的结点,从项目起点到终点进行排列;
2)用有方向的线段标出各结点的紧前活动和紧后活动的关系,使之成为一个有方向的网络图;
3)用正推法和逆推法计算出各个活动的最早开始时间,最晚开始时间,最早完工时间和最迟完工时间,并计算出各个活动的时差;
4)找出所有时差为零的活动所组成的路线,即为关键路径;
2.2基本要求:
(1)选取建图的一种算法建立图;
选取邻接表的算法来建立图,是一种顺序+链式存储结构。
用顺序表存放顶点,为每个顶点建立一个单链表,单链表中的结点表示依附于该顶点的边或以该顶点为尾的弧。
(2)两个相邻顶点与它们之间的边表示活动,边上的数字表示活动延续的时间
参照该工程所化的AOE-网,求出从起点到终点的所有路径,然后通过拓扑排序和逆拓扑排序求出最早与最晚发生时间,找出长度最大的路径,从而求得关键路径。
2.3目的:
在该部分,即需求分析中,根据设计题目的要求,充分地分析和理解问题,叙述系统的功能要求,明确问题要求做什么,以及限制条件是什么。
程序所能达到的功能:
通过输入所要构建的图的顶点数,弧数,创建图,并打印出来,对图进行拓扑排序,求得此图的最早发生时间和最迟发生时间,并求得关键活动和关键路径,打印出来。
概要设计
3概要设计
3.1算法分析:
(1)求关键路径必须在拓扑排序的前提下进行,有环图不能求关键路径;
(2)只有缩短关键活动的工期才有可能缩短工期;
(3)若一个关键活动不在所有的关键路径上,减少它并不能减少工期;
(4)只有在不改变关键路径的前提下,缩短关键活动才能缩短整个工期。
(5)关键路径:
从源点到汇点的路径长度最长的路径叫关键路径。
(6)活动开始的最早时间e(i);
(7)活动开始的最晚时间l(i);
(8)定义e(i)=l(i)的活动叫关键活动;
(9)事件开始的最早时间ve(i);
(10)事件开始的最晚时间vl(i)。
设活动ai由弧(即从顶点j到k)表示,其持续时间记为dut(vj,k>),则:
e(i)=ve(j)
l(i)=vl(k)-dut()
求ve(i)和vl(j)分两步:
1.从ve
(1)=0开始向前递推
ve(j)=Max{ve(i)+dut()}
T,2<=j<=n
其中,T是所有以j为弧头的弧的集合。
2.从vl(n)二ve(n)开始向后递推
vl(i)=Min{vl(j)-dut()}
S,1<=i<二n-1
其中,S是所有以i为弧尾的弧的集合。
两个递推公式是在拓扑有序和逆拓扑有序的前提下进行。
3.2算法步骤:
(1)输入e条弧vj,k>,建立AOE网的存储结构。
⑵从源点v1出发,令ve
(1)=0,求ve(j),2<=j<=n。
⑶从汇点vn出发,令vl(n)二ve(n),求vl(i)1<=i<=n-1。
(4)根据各顶点的ve和vl值,求每条弧s(活动)的最早开始时间e(s)和最晚开始时间l(s),其中e(s)=l(s)的为关键活动。
3.3数据结构:
3.3.1数据结构:
typedefstructnode/边表结点
{
intadjvex;//邻接点编号
intdut;//弧的信息
structnode*next;〃下一条弧指针
}edgenode;
typedefstruct//顶点表结点
{
intprojectname;//顶点域
intid;//顶点的入度信息
edgenode*link;//边表头指针
}vexnode;
3.3.2程序模块:
intmain()
界面程序的主函数
voidseekkeyroot()
求关键路径的主函数
voidCreateGraphic(vexnode*Graphicmap,intprojectnumber,intactivenumber)函数建立AOE图
intSearchMapPath(vexnode*Graphicmap,intprojectnumber,intactivenumber,int&
totaltime)
求出最大路径,并打印出关键路径
3.3.3各模块间的调用关系:
主函数voidmain()
要调用:
求关键路径的函数seekkeyroot();
求关键路径的函数seekkeyroot()
要调用:
创建图的函数CreateGraphic(Graphicmap,projectnumber,activenumber)
求最大路径并打印出关键路径的函数intSearchMapPath(vexnode*
Graphicmap,intprojectnumber,intactivenumber,int&totaltime)
详细设计
4详细设计
4.1主要函数的核心代码:
1.创建图的函数
2.求出最大路径,并打印出关键路径的函数
3.球关键路径的函数
4.主函数
具体代码请见附录:
源程序清单
4.2程序流程图:
测试
5测试
1.开始界面
c=<'T:
\Documerrtsand5ettihgs\Admftitetratot-\Debug\aOi.exe欢迎逬入求关犍路径算法程序
m涎m开始输入王程的节点数据并求出关犍路径
e请输入选择三
2.进入求关键路径的系统
3lsC:
\DocymentsandSettings.Adniinjstzrator\Debug\00.exe*1
★盘★住匸亡
欢迎进入求关撻路径算法程序
沁》开始输入工程的节点数据并求出关犍路径
e|请输入选择垢
输入符合标准,欢迎逬入求关桃路径的系统?
请输入这个项S的AOE-翩的节点数:
2.输入节点数和活动个数
3.输入某项目的信息(弧头,弧尾,权值)
-i
★住★盘★凸*住★住★☆女旳凸★矗★曲★农余去★☆女☆★旳*
欢迎进入求关犍路径算法程序
☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
◎沁〉开始输入工程的节点数据并求岀关犍路径
e晴输入选择*
输入符台标准,欢迎进入求关键路径的系统学
数个点动节活的旳网网E-E-oO目目项项个个AA请请
33
请河
权值);
(1,3,5
4.打印出关键路径
5.课本上图7.29的程序测试
求上述AOE网的操作为:
恂鑑:
权值)
^11123455678
终点
4
?
8
最早开始时间
0
0
0
6
4
5
7
?
7
1&
14
最迟完威时冋
3
2
0
6
6
8
7
7
10
16
14
3
2
8
2
3
0
0
3
0
8
备注
关犍活动<5,8>
关犍惜易<「7>
关犍活动
>?
>
矣犍常易<8>9>
请揃入这个项§的肋E-网的节点数;9请输入这个项目的RQE-网的活动个数:
11
请输入某项目的信凰迤酵羽彗褪即代表鰭点i与4之问的活
蠶霞蠶專最短站我环单位时间
求的关键路径为:
5.错误测试
应输入的数为整形,若输入非整形的数据,则程序遇到问题关闭
欢迎进入求关键路径算法程序
OO-ewe
00.遇到问题需要关闭"我们对此寸起的不便表示抱歉・
如果您正处于讲程当中>信息有可能丢失口
关于此错俣的苴他信息>
谙单击吐处•一
主冃青
调试⑻
厂荒闭©-!
6.回路测试
总结
6总结
历时一周的课程设计终于结束了,现在来做一下总结。
首先,关于程序方面,我发现即使对设计思路有了眉目,知道了所要用到的数据结构、用邻接表来存储AOE-网、建立栈来求拓扑序列、输出的拓扑序列的个数少于节点数则有回路等等,要把这些方法写成函数代码,其实还是一件非常不容易的事情。
再加上要完善设计思路,构造整个程序框架在内,都是一件工作量非常大的工作。
幸好,有很多资料可以在网路上搜到。
所以课程设计的第一天,我们搜集了很多关于关键路径的资料,包括几种不同思路的程序代码,以及程序流程。
然后我们的工作就变成:
看懂并整理这些代码,然后再其基础上增加自己需要的功能,按照自己的意愿来修改与完善。
在处理程序代码的时候,有两个问题始终解决不了。
一是程序输入时只能输入整形数据,而非整形的输入则会导致程序异常停止,但是因为整形的输
入方式已贯穿整个程序,若要修改只能另外重做整个程序,所以暂不考虑修改,而打算做一个判错系统,判断若非整形的输入则报错;二是第一种错误的解决方案未能成功实行,于网路上搜索到了几种判断是否为整形数据的程序代码,但将其修改融合到求关键路径的程序中,虽然没有错误可以运行,但是却不能正确的报错。
于是,在尝试多种方案却仍不成功的前提下,我只好选择加上提示语,即:
printf("请输入某项目的信息,并请用整形数字表示(格式:
弧头,弧尾,
权值):
\n");
printf("例如:
输入1,2,4即代表结点1与4之间的活动需要4个时间单位。
\n");
这是这次课程设计中最大的两个遗憾。
不过在操作界面的人性化上,我倒尽可能的做得很完善,无论从美观角度
还是方便清楚操作,都实行了非常人性化的方式。
因为通常清楚程序的人,知道怎么操作以及该输入什么,而不清楚的人却有很大可能在细节方面输入错误导致程序运行失败,或是根本不知道应该怎么输入。
所以,尽可能的人性化的设计是非常有必要的,让不懂程序的人也可以正确的操作运行。
其次,关于课程设计报告方面,老师对我们的要求非常严格,对课程设计报告的要求与毕业设计的格式相当,以便为大四时做毕业设计打下良好的基础。
初期,因为之前为了搜集资料模板,有参考一下已经做完数据结构课设的对日班即十二班的报告,发现她们的报告相当简单,所以确实觉得老师对我们要求太严了,虽然看似简单,但一大堆的要求、规定、格式等,完成起来却真的很麻烦也很辛苦。
然而,经过了几天的“努力报告ing~~~”的状态,常常一弄就弄很长时间,时常做到很晚还在做报告内容、目录、页眉页脚、程序截图,,再加上关键路
径的课程内容,是在十几辛苦又充实。
虽然辛苦程度相差很远,但也有些明白大四的学生为什么几乎没课却也整天在那里做毕业设计了
我认为这样的课程设计比较有意义,独立完成资料的搜集以及课设的内容,然后独立的做出报告,让这个过程很完整,无论是知识方面、还是报告的书写方面,都学到了更多的东西,为毕业设计打下了良好的基础。
最后,做再次一下总结。
程序方面仍有为解决的问题,希望即便课设之后也可以努力将问题解决掉。
然后关键路径的算法中,有些知道怎么做却很难清楚回答出来的问题,希望可以再好好的查找一下相关资料,将知识系统化、理论化、规范化。
参考文献
[1]严蔚敏,吴伟民.数据结构.北京:
清华大学出版社,2006.
[2]谭浩强.C程序设计(第二版)作者:
清华大学出版社,2006
附录:
源程序清单
#include
#include
#include
#includetypedefstructnode//边表结点
{
intadjvex;//邻接点编号
intdut;//弧的信息
structnode*next;//下一条弧指针
}edgenode;
typedefstruct//顶点表结点
{
intprojectname;//顶点域
intid;//顶点的入度信息
edgenode*link;//边表头指针
}vexnode;
voidCreateGraphic(vexnode*Graphicmap,intprojectnumber,intactivenumber)//仓U建图
{
intbegin,end,duttem;//分别代表弧的前节点,尾节点,活动时间
edgenode*p;//边表头指针
for(inti=0;i{
Graphicmap[i].projectname=i;〃顶点的命名按0,1,2,3
Graphicmap[i].id=0;//顶点的信息的度数均赋为零
Graphicmap[i].link=NULL;
}
printf("\n");
printf("请输入某项目的信息,并请用整形数字表示(格式:
弧头,弧尾,权值):
\n");
printf(”例如:
输入1,2,4即代表结点1与4之间的活动需要4个时间单位。
\n");
为活动的数目,即弧的条数
printf("\n");
p->adjvex=end-1;//p->dut=duttem;//
因为是从零开始记的,姑要减一,就是让终点插入到邻接表内该弧的活动时间为duttem
for(intk=0;kscanf("%d,%d,%d",&begin,&end,&duttem);//p=(edgenode*)malloc(sizeof(edgenode));//
请输入第%4条的起点、终点和权值临时分配存储空间
Graphicmap[end-1].id++;//入度加一
p->next=Graphicmap[begin-1].link;
Graphicmap[begin-1].link=p;//让下一个节点作为下一插入节点的前驱节点}
}
intSearchMapPath(vexnode*Graphicmap,intprojectnumber,intactivenumber
int&totaltime)//求出最大路径,并打印出关键路径
{
inti,j,k,m=0;
intfront=-1,rear=-1;
int*topologystack=(int*)malloc(projectnumber*sizeof(int));//int*vl=(int*)malloc(projectnumber*sizeof(int));//许最迟发生的时间
int*ve=(int*)malloc(projectnumber*sizeof(int));//
int*l=(int*)malloc(activenumber*sizeof(int));//
int*e=(int*)malloc(activenumber*sizeof(int));//edgenode*p;//边表头的指针
totaltime=0;//存放整个工程的最短时间
用来保存拓扑排列
用来表示在不推迟整个工程的前提下,
用来表示Vj最早发生时间用来表示活动Ai最迟完成开始时间
表示活动最早开始时间
VJ允
for(i=0;i先把每个工程的最早发生时间初始化为零
for(i=0;iif(Graphicmap[i].id==0)
{
topologystack[++rear]=i;//让所有的头节点入队列m++;//记录入队列的顶点个数
}
}while(front!
=rear)
{
front++;//出队列
j=topologystack[front];//拓扑排序的节点依次出队列m++;//记录入队列的节点个数
p=Graphicmap[j].link;//
指向顶点指向的下一个顶点
while(p)
{
k=p->adjvex;//邻接点编号
Graphicmap[k].id--;//
让入度减一,相当于删除一个入度为零的前驱节点,和相关的弧
if(ve[j]+p->dut>ve[k])//
将最长的路径赋给VE[K]
ve[k]=ve[j]+p->dut;
if(Graphicmap[k].id==0)//如果入度为零,则入队列topologystack[++rear]=k;
p=p->next;//指向下一个节点
}
if(m{
printf("\n本程序所建立的图有回路不可计算出关键路径!
\n");
printf("将退出本程序!
\n");
return0;
}
totaltime=ve[projectnumber-1];//最短完成时间即为最后一个节点所累加的时间之和
for(i=0;ivl[i]=totaltime;
for(i=projectnumber-2;i>=0;i--)〃用逆拓扑排序来求活动Ai最迟完成开始时间,即从最后一个节
点减去最短的时间
{
j=topologystack[i];
p=Graphicmap[j].link;
while(p)
{
k=p->adjvex;
if((vl[k]-p->dut)vl[j]=vl[k]-p->dut;
p=p->next;
}
}
i=0;
printf("\n");
printf("|起点|终点|最早开始时间|最迟完成时间|差值|备注\n");
for(j=0;j{
p=Graphicmap[j].link;
while(p)
{
k=p->adjvex;
e[++i]=ve[j];
l[i]=vl[k]-p->dut;
printf("|%4d|%4d|%11d|%11d|%3d|",Graphicmap[j].projectname
+1,Graphicmap[k].projectname+1,e[i],l[i],l[i]-e[i]);
if(l[i]==e[i])//当差值为零时,则为关键路径
printf("关键活动<%2d,%4d>",
Graphicmap[j].projectname+1,Graphicmap[k].projectname+1);
printf("\n");