ImageVerifierCode 换一换
格式:DOCX , 页数:28 ,大小:359.09KB ,
资源ID:7169846      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7169846.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(数据结构课程设计拓扑排序和关键路径.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

数据结构课程设计拓扑排序和关键路径.docx

1、数据结构课程设计拓扑排序和关键路径1 ABSTRACT1.1图和栈的结构定义struct SqStack/栈部分 SElemType *base;/栈底指针 SElemType *top;/栈顶指针 int stacksize;/栈的大小 int element_count;/栈中元素个素;/AOE网的存储结构struct ArcNode /表结点 int lastcompletetime;/活动最晚开始时间 int adjvex; /点结点位置 int info; /所对应的弧的权值 struct ArcNode *next;/指向下一个表结点指针;struct VNode /点结点 Ver

2、texType data; /结点标志 int indegree; /该结点入度数 int ve; /记录结点的最早开始时间 int vl; /记录结点的最晚开始时间 struct ArcNode *first_out_arc; /存储下一个出度的表结点 struct ArcNode *first_in_arc;/存储下一个入度的表结点;struct ALGraph VNode *vertices; /结点数组 int vexnum; /结点数 int arcnum; /弧数 int kind; /该图的类型 ;2 系统总分析2.1关键路径概念分析2.1.1什么是关键路径关键路径法(Criti

3、cal Path Method, CPM)最早出现于20世纪50年代,它是通过分析项目过程中哪个活动序列进度安排的总时差最少来预测项目工期的网络分析。这种方法产生的背景是,在当时出现了许多庞大而复杂的科研和工程项目,这些项目常常需要运用大量的人力、物力和财力,因此如何合理而有效地对这些项目进行组织,在有限资源下以最短的时间和最低的成本费用下完成整个项目就成为一个突出的问题,这样CPM就应运而生了。 对于一个项目而言,只有项目网络中最长的或耗时最多的活动完成之后,项目才能结束,这条最长的活动路线就叫关键路径(Critical Path),组成关键路径的活动称为关键活动。2.1.2关键路径特点 关

4、键路径上的活动持续时间决定了项目的工期,关键路径上所有活动的持续时间总和就是项目的工期。 关键路径上的任何一个活动都是关键活动,其中任何一个活动的延迟都会导致整个项目完工时间的延迟。 关键路径上的耗时是可以完工的最短时间量,若缩短关键路径的总耗时,会缩短项目工期;反之,则会延长整个项目的总工期。但是如果缩短非关键路径上的各个活动所需要的时间,也不至于影响工程的完工时间。 关键路径上活动是总时差最小的活动,改变其中某个活动的耗时,可能使关键路径发生变化。可以存在多条关键路径,它们各自的时间总量肯定相等,即可完工的总工期。 关键路径是相对的,也可以是变化的。在采取一定的技术组织措施之后,关键路径有

5、可能变为非关键路径,而非关键路径也有可能变为关键路径。 2.2关键路径实现过程2.2.1结构选取首先要选取建图的一种算法建立图,有邻接矩阵,邻接表,十字链表,邻接多重表等多种方法,要选取一种适当的方法建立图,才能提高算法效率,降低时间复杂度和空间复杂度。两个相邻顶点与它们之间的边表示活动,边上的数字表示活动延续的时间。对于给出的事件AOE网络,要求求出从起点到终点的所有路径,经分析、比较后找出长读最大的路径,从而得出求关键路径的算法,并给出计算机上机实现的源程序。完成不同路径的活动所需的时间虽然不同,但只有各条路径上所有活动都完成了,这个工程才算完成。2.2.2具体要解决的问题(1) 将项目中

6、的各项活动视为有一个时间属性的结点,从项目起点到终点进行排列; (2) 用有方向的线段标出各结点的紧前活动和紧后活动的关系,使之成为一个有方向的网络图; (3) 用正推法和逆推法计算出各个活动的最早开始时间,最晚开始时间,最早完工时间和最迟完工时间,并计算出各个活动的时差; (4) 找出所有时差为零的活动所组成的路线,即为关键路径; (5) 识别出准关键路径,为网络优化提供约束条件;2.2.3算法分析(1)求关键路径必须在拓扑排序的前提下进行,有环图不能求关键路径;(2)只有缩短关键活动的工期才有可能缩短工期;(3)若一个关键活动不在所有的关键路径上,减少它并不能减少工期; (4)只有在不改变

7、关键路径的前提下,缩短关键活动才能缩短整个工期。(5)关键路径:从源点到汇点的路径长度最长的路径叫关键路径。(6)活动的最早开始时间e(i);(7)活动的最晚开始时间l(i);(8)定义e(i)=l(i)的活动叫关键活动;(9)事件的最早开始时间ve(i);(10)事件的最晚开始时间vl(i)。设活动ai由弧(即从顶点j到k)表示,其持续时间记为dut(),则: 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

8、)=ve(n)开始向后递推 vl(i)=Min vl(j)-dut() S,1=i=n-1 其中,S是所有以i为弧尾的弧的集合。两个公式是在拓扑有序和逆拓扑有序的前提下进行。2.2.4 算法步骤(1)输入e条弧,建立AOE网的存储结构。(2)从源点v1出发,令ve(1)=0,求个点的最早开始时间ve(j)。(3)从汇点vn出发,令vl(n)=最大值,求个点的最晚开始时间vl(j)。(4)由于各结点的最早开始时间已求出来,所以各活动的最早开始时间即(每条弧s(活动)的最早开始时间)就等于该结点的最早开始时间,并由 上可同时求出该活动的最晚开始时间l(j)。(5)具体表达式为: e(i)=ve(j

9、) l(i)=vl(k)-dut() (6)当结点的最早开始时间ve(j)=最晚开始时间时vl(j),则该结点为关键结点。 (7)当活动的最早开始时间e(j)=最晚开始时间时l(j),则该结点为关键活动。3 主要功能模块设计3.1程序模块栈部分模块Status InitStack(SqStack &S) /初始化栈Status DestroyStack(SqStack &S)/销毁栈Status ClearStack(SqStack &S)/清空栈Status StackEmpty(SqStack S)/判断是否为空Status StackEmpty(SqStack S)/判断是否为空Stat

10、us Pop(SqStack &S,SElemType &e) /弹出元素Status GetElement(SqStack &S,int position,SElemType &e) /取元素,非弹出,i为要去元素位置无向图(AOE网)部分模块void CreateALGraph(ALGraph &graph)/初始化AOE网Status TopologicalSort(ALGraph &graph,SqStack &ToPoReverseSort) /求拓扑排序Status PutInfoToPoSort(SqStack temp,ALGraph graph) /输出拓扑顺序排序(当拓扑序

11、列存在时)Status GetVeAndVl(ALGraph &graph,SqStack OrderSort,SqStack RevSort) /求出结点和活动的最晚开始时间和最早开始时间Status CriticalPath(ALGraph &graph,SqStack RevSort) /求出关键活动和关键事件并输出4 系统详细设计4.1主函数模块 main函数首先调用SqStack ToPoSort;SqStack ToPoReverseSort;函数来定义栈,调用InitStack(ToPoSort);来初始化存拓扑排序的栈和InitStack(ToPoReverseSort);来初

12、始化逆拓扑排序的栈。其次调用CreateALGraph(ALGraph &graph)函数定义和初始化AOE网,调用TopologicalSor t(ALGraph &graph,SqStack &ToPoReverseSort) 函数求拓扑序列和调用PutInfoToPoSort(ToPoSort,graph);函数来输出输出拓扑顺序排序。 然后调用GetVeAndVl(graph,ToPoSort,ToPoReverseSort) 函数求结点和活动的最晚开始时间、最早开始时间并输出。 最后调用Status CriticalPath(ALGraph &graph,SqStack RevSor

13、t)函数来求关键活动、关键事件并输出。4.2初始化模块 初始化模块用来初始化图,要求用户自己输入数据,并程序构造AOE网。本程序是用自己改进的邻接表来构造AOE网。见图2-4-2 4.3求拓扑序列模块 利用栈来存储入度为零的结点,然后逐个弹出,来进行与该结点的出度结点来比较,是否符合拓扑排序的规则,最后用ToPoReverseSort存放拓扑逆序序列来完成整个拓扑排序。见图2-4-34.4求最晚开始时间和最早开始时间模块 (包括结点和活动的最早和最晚开始时间)见图2-4-44.5关键活动和关键事件 见图2-4-54.6输出模块 输出相应结点的信息,拓扑序列,以及事件的最早开始时间和最晚开始时间

14、,输出相应的活动的最早开始时间和最晚开始时间,关键活动以及关键事件。5 测试分析5.1测试内容 求的关键路径为:程序输入部分:求拓扑序列部分求结点和活动的最早开始时间和最晚开始时间输出图中的关键事件和关键活动(关键路径)测试关键路径结果:5.2回路测试结果分析:结果完全符合所求,但是输出的方面不够完美,并且自我感觉程序所使用的空间比较大,算法复杂度较高,所以效率比较低下,当程序输入存在有环的时候,程序没有发生任何错误,直接输出“图存在有环”然后退出程序。 由此可见本程序计划实施到完工比较顺利的完成了,并且在程序测试中能够得到预期的结果出来,不过唯一不满意的是程序过于复杂化,使用的太多的空间,致

15、使程序成为一个缺陷。参考文献1严蔚敏,吴伟民.数据结构. 北京:清华大学出版社,2006.2谭浩强. C程序设计(第二版)作者:清华大学出版社,2006心得体会 经历几天的编程之后,课程设计终于结束了。 一开始整个程序不知道怎么开始,而且算法是怎么样的都不知道,不过经过一番的查书、翻阅资料、上网查找之后终于了解到整个算法流程以及实现,首先,关键路径的实现是用邻接表来存储的,对于这个来说,本人觉得单纯按照书本的邻接表来做不太合适,于是就自己改进了一个邻接表,加上在结点里加上存储入度的变量,和加上指向所以入度的表的指针。并且在表结构上加上入度表结构。 由于搜集了很多关于关键路径的资料,包括几种不同

16、思路的程序代码,以及程序流程。然后看懂并整理这些代码,然后再其基础上增加自己需要的功能,按照自己的意愿来修改与完善。 在程序输入部分采用结点,结点,弧(即结点和结点之间的权值),由于输入贯穿整个程序部分,所以输入部分十分重要。之后创建整个程序的结构,其中包括入度和出度的表结点,这两个都依附在结点结构之上。 在程序求关键路径的时候,首先必须要求出整个图的拓扑排序,并用栈来保存起来,然后并在主函数里定义了两个栈,分别来存储顺序拓扑排序和逆序拓扑排序,其中在求拓扑排序的时候就遇到了一个问题就是结点存储的度数发生变化了,这个问题在后来的时候才发现的,因为之后还需要用到入度数,由此,在求拓扑序列的时候必

17、须把入度数先用一个数组来存起来,然后求完拓扑序列之后必须把整个结点的入度数还原。/保留入度度数/ int *indegree_copy=(int *)malloc(sizeof(int)*graph.vexnum); for(i=0;iindegree ; /还原入度度数/ for(i=0;iindegree=*(indegree_copy+i) ; / 最后按照拓扑的顺序序列求出结点的最早开始时间,但是源结点的最早开始时间必须赋予一定的值,所以按照顺序的拓扑序列并且还可以求出活动的最早开始时间。再次,按照逆序拓扑序列来求出结点和活动的最晚开始时间。然后根据算法就可以轻易的求出关键路径和关键事

18、件。 其中在编译过程中出现了一个编译的异常,上网找了一下,说是指针越界了,于是,再设断点等手段经过长时间的摸索之后就发现了原来是程序中的栈的部分出问题了,由于之前都没有过栈出问题的情况,于是就改变了一下这个问题就没出现过了。教师评语附 录程序源代码:/ 关键路径.cpp : 定义控制台应用程序的入口点。#include stdafx.h#include#include#define VertexType int/栈部分#define STACK_ADDITION sizeof(SElemType)#define SElemType int#define OK true#define ERROR

19、 false#define Status boolstruct SqStack SElemType *base; SElemType *top; int stacksize; int element_count;/元素个素;Status InitStack(SqStack &S) /初始化栈 S.base =(SElemType *)malloc(STACK_ADDITION); S.stacksize =STACK_ADDITION; S.element_count =0; if(S.base =NULL) printf(malloc errorn); exit(0); else S.top

20、=S.base ; return OK;Status DestroyStack(SqStack &S)/销毁栈 if(S.base=NULL) printf(Stack is not existentn); else delete(S.base); return OK;Status ClearStack(SqStack &S)/清空栈 if(S.base=NULL) printf(Stack is not existentn); else if(S.base =S.top ) printf(Sack is NULLn); else S.top=S.base ; S.element_count

21、=0; return OK;Status StackEmpty(SqStack S)/判断是否为空 if(S.base=NULL) printf(Stack is not existentn); return false; if(S.top =S.base ) return true; else return false; Status Push(SqStack &S,SElemType e) /增加元素 SElemType *temp1=S.base; SElemType *temp2=S.top; if(S.stacksize-(S.element_count *STACK_ADDITIO

22、N)=STACK_ADDITION) S.base = (SElemType *)realloc(S.base ,(S.stacksize+STACK_ADDITION); S.stacksize+=STACK_ADDITION; S.top =S.base + (temp2-temp1); *S.top =e; S.top =S.top +1; S.element_count+; else *S.top =e; S.top =S.top+1; S.element_count+; return OK;Status Pop(SqStack &S,SElemType &e) /弹出元素 if(S.

23、top=S.base ) printf(Stack is null! Pop error!n); return false; else e=*-S.top ; S.element_count -; return OK; int StackLength(SqStack S) return S.element_count ;Status GetElement(SqStack &S,int position,SElemType &e) /取元素,非弹出,i为要去元素位置 SElemType *temp; temp=S.top; if(S.top=S.base ) printf(Stack is nu

24、ll! GetElement error!n); return false; else if(position=S.element_count) e=*(temp-position); return OK; else printf(error!由于输入位置比栈元素数目大); return false; /=struct ArcNode /表结点 int lastcompletetime;/活动最晚完成时间 int adjvex; /点结点位置 int info; /所对应的弧的权值 struct ArcNode *next;/下一个表结点;struct VNode /点结点 VertexTyp

25、e data; /标志 int indegree; /该结点入度数 int ve; /记录最早开始时间 int vl; /记录最晚开始时间 struct ArcNode *first_out_arc; /存储下一个出度的表结点 struct ArcNode *first_in_arc;/存储下一个入度的表结点;struct ALGraph VNode *vertices; /结点数组 int vexnum; /结点数 int arcnum; /弧数 int kind; /该图的类型;void CreateALGraph(ALGraph &graph) int temp1=1; int temp

26、2=0; int temp3=0;/权 int i=0; struct ArcNode *arc1=NULL; struct ArcNode *arc2=NULL; printf(请输入结点数(结点由1开始)和图的类型:n); scanf(%d %d,&graph.vexnum,&graph.kind ); graph.vertices =(VNode *)malloc(graph.vexnum+1)*sizeof(VNode); for(i=0;idata=i; (graph.vertices+i)-first_in_arc =NULL; (graph.vertices+i)-first_o

27、ut_arc=NULL; (graph.vertices+i)-ve =0; (graph.vertices+i)-vl=0; (graph.vertices+i)-indegree =0; printf(请输入(格式:点,点,两点之间的权值n); graph.arcnum =-1; while(!(temp1=0&temp2=0&temp3=0) graph.arcnum+; /图的弧数 scanf(%d %d %d,&temp1,&temp2,&temp3); (graph.vertices +temp2)-indegree) +; if(graph.vertices+temp2)-fir

28、st_in_arc=NULL) (graph.vertices+temp2)-first_in_arc =(ArcNode *)malloc(sizeof(ArcNode); (graph.vertices+temp2)-first_in_arc-adjvex =temp1; (graph.vertices+temp2)-first_in_arc-info =temp3; (graph.vertices+temp2)-first_in_arc-lastcompletetime =0;/活动最晚完成时间初始化 (graph.vertices+temp2)-first_in_arc-next =NULL; else arc2=(graph.vertices+tem

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1