1、关键路径问题c语言实习课程论文西北农林科技大学信息工程学院C语言和数据结构实习报告题 目: 关键路径问题 学 号姓 名专业班级软件093指导教师实践日期目 录一、综合训练目的与要求 3二、综合训练任务 3三、总体设计 3四、详细设计说明 4五、调试与测试 7六、实习日志 10七、实习总结 12八、附录:核心代码清单 12一、综合训练目的与要求本综合训练是计算机科学与技术、信息管理与信息系统、软件工程专业重要的实践性环节之一,是在学生学习完程序设计语言(C)、数据结构课程后进行的一次全面的综合练习。本课综合训练的目的和任务:1. 巩固和加深学生对C语言、数据结构课程的基本知识的理解和掌握;2.
2、掌握C语言编程和程序调试的基本技能;3. 利用C语言进行基本的软件设计;4. 掌握书写程序设计说明文档的能力;5. 提高运用C语言、数据结构解决实际问题的能力。二、综合训练任务基本要求:(1)对一个描述工程的AOE网,建立其存储结构;(注:数据的输入可以是键盘输入或文件输入两种方式)(2)判断该AOE网是否能够顺利进行。(3)若该工程能顺利进行,输出完成整项工程至少需要多少时间,以及每一个关键活动所依附的两个顶点、最早发生时间、最迟发生时间。(注:结果的输出可以是屏幕输出和文件输出两种方式)三、总体设计主流程图四、详细设计说明对于问题的分析: 由于在AOE-网中有些活动可以并行进行,所以完成工
3、程的最短时间就是从开始点到完成点的最长路径的长度,所以路径长度最长的路径叫做关键路径。 求关键路径的算法: (1)输入e条弧,建立AOE-网的存储结构; (2)从源点V0出发,令Ve0=0,按拓扑有序求其余各定点的最早发生时间Vei(1=i=i=2); (4)根据各顶点的Ve和Vl值,求每条弧s的最早开始时间e(s)和最迟开始时间l(s).。若某条弧满足条件e(s)=l(s),则为关键活动。如上所述,计算各顶点的Ve值是在拓扑排序的过程中进行的,需要对拓扑排序的算法作如下修改: (a)在拓扑排序之前设初值,令 Vei=0(0=i=n-1); (b)在算法中增加一个计算Vj的直接后继Vk的最早发
4、生时间的操作:若Vej+dut()Vek,则 Vek= Vej +dut(); (c)为了能按逆拓扑有序序列的顺序计算各顶点的Vl值,需要记下在拓扑排序的过程中求得的拓扑有序序列,这需要在拓扑排序算法中,增设一个栈以记录拓扑有序序列,则在计算机求得各顶点的Ve值以后,从栈顶至栈底便为逆拓扑有序序列。 在程序末端要对程序进行改进,使其输入具有键盘输入和文件输入两种方式,输出也具有键盘输出和文件输出两种方式。本程序所需要的结构体及宏定义如下:#define OK 1#define INFEASIBLE -1#define OVERFLOW -2#define MAX_VERTEX_NUM 20 /
5、最大顶点个数 图的#define STACK_INIT_ZSIZE 100 /存储空间初始分配量 栈的#define STACKINCREMENT 10 /存储空间分配增量 栈的typedef int Status; /类型typedef int SElemType;typedef int VertexType;typedef int InfoType;/-栈结构-typedef struct SElemType *base; /在栈构造之前和销毁之后,base的值为NULL SElemType *top; /栈顶元素 int stacksize; /当前已分配的存储空间,以元素为单位SqSt
6、ack,*Stack;/-图结构-typedef struct ArcNode /表结点 int adjvex; /该弧所指向的顶点的位置 struct ArcNode *nextarc; /指向下一条弧的指针 int info; /该弧的相关信息的指针 ArcNode;typedef struct VNode /头结点 VertexType data; /顶点信息 ArcNode * firstarc; /指向第一条依附该顶点的弧的指针VNode,AdjListMAX_VERTEX_NUM;typedef struct /图信息 AdjList vertices; int vexnum,ar
7、cnum; /图的当前顶点数和弧数 int Inclnfo; int kind ; /图的种类标志ALGraph;主要功能函数为:Status InitStack(Stack S); /构造一个空栈SStatus Push (Stack S,SElemType e);/入栈Status Pop(Stack S,SElemType *e); /出栈上述三个函数则在实现拓扑排序以及关键路径的算法中需要用到。void FindInDegree(ALGraph G,int *indegree); /求顶点的入度求顶点的入度函数则是在拓扑排序中用到,配合栈的函数。int LocateVex(ALGrap
8、h G,int u); /返回顶点v在图顶点向量中的位置返回顶点的位置,则运用在构造邻接表的函数中。void CreateADG(ALGraph *G);键盘输入 -建立邻接表int FileCreateADG(char sourceFileName,ALGraph *G); 文件输入 -建立邻接表void FilePrint(ALGraph G);文件输出邻接表void Print(ALGraph G);屏幕打印邻接表Status TopologicalOrder(ALGraph G,Stack T);拓扑排序Status FileCriticalPath(ALGraph G);文件输出关键
9、路径Status CriticalPath(ALGraph G);屏幕打印关键路径int DrawPrint();屏幕开始欢迎介绍void PrintG2File(ALGraph G);判断是否文件输入void PrintfG2Screen(ALGraph G);判断是否文件输入int selet();整体算法排序int selet2();结束画面函数五、调试与测试下面先进行对于问题的人工测试:【例一】下面是分析所得:图 7.21 是一个网。其中有 9 个事件 v 1 , v 2 , , v 9 ; 11 项活动 a 1 , a 2 , , a 11 。每个事件表示在它之前的活动已经完成,在它
10、之后的活动可以开始。如 v 1 表示整个工程开始, v 9 表示整个工程结束。 V 5 表示活动 a 4 和 a 5 已经完成,活动 a 7 和 a 8 可以开始。与每个活动相联系的权表示完成该活动所需的时间。如活动 a 1 需要 6 天时间可以完成。 (1)AOV 网具有的性质 只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始。 只有在进入某一顶点的各有向边所代表的活动都已经结束,该顶点所代表的事件才能发生。 表示实际工程计划的 AOE 网应该是无环的,并且存在唯一的入度过为 0 的开始顶点和唯一的出度为 0 的完成顶点。(2)由事件 v j 的最早发生时间和最晚发
11、生时间的定义 , 可以采取如下步骤求得关键活动 : 1. 从开始顶点 v 1 出发 , 令 ve(1)=0, 按拓朴有序序列求其余各顶点的可能最早发生时间。 Ve(k)=maxve(j)+dut() ( 7.1 ) j T 其中 T 是以顶点 v k 为尾的所有弧的头顶点的集合 (2 k n) 。 如果得到的拓朴有序序列中顶点的个数小于网中顶点个数 n ,则说明网中有环,不能求出关键路径,算法结束。 2. 从完成顶点 v n 出发,令 vl(n)=ve(n) ,按逆拓朴有序求其余各顶点的允许的最晚发生时间 : vl(j)=minvl(k)-dut() k S 其中 S 是以顶点 v j 是头的
12、所有弧的尾顶点集合 (1 j n-1) 。 3. 求每一项活动 a i (1 i m) 的最早开始时间 e(i)=ve(j) ;最晚开始时间 l(i)=vl(k)-dut() 。若某条弧满足 e(i)=l(i) ,则它是关键活动。 对于图 7.21 所示的 AOE 网,按以上步骤的计算结果见表 7.3 ,可得到 a 1 , a 4 , a 7 , a 8 , a 10 , a 11 是关键活动。 (3)求出 AOE 网中所有关键活动后,只要删去 AOE 网中所有的非关键活动,即可得到 AOE 网的关键路径。这时从开始顶点到达完成顶点的所有路径 都是关键路径。一个 AOE 网的关键路径可以不止一
13、条,如图 7.21 的 AOE 网中有二条关键路径, ( v 1 , v 2 , v 5 , v 7 , v 9 ) 和 ( v 1 , v 2 , v 5 , v 8 , v 9 ) 它们的路径长度都是 16 。如图 7.24 所示。 下面有程序所得的结果:关键活动为:从1到 2的关键路径是 6,发生时间为:0从2到 5的关键路径是 1,发生时间为:6从5到 8的关键路径是 7,发生时间为:7从5到 7的关键路径是 9,发生时间为:7从7到 9的关键路径是 2,发生时间为:16从8到 9的关键路径是 4,发生时间为:14其中分析所得与程序所得相同。下面简单再多列举几个例子进行调试与测验:【例
14、二】顶点数:5 边数:6第一条边的信息:由12 ,权值为2第二条边的信息:由13 ,权值为3第三条边的信息:由14 ,权值为4第四条边的信息:由23 ,权值为2第五条边的信息:由35 ,权值为5第六条边的信息:由45 ,权值为6分析所得关键路径为:145,时间长度为10;由程序所得:关键活动为:从1到 4的关键路径是 4,发生时间为:0从4到 5的关键路径是 6,发生时间为:4分析与程序所得相同。【例三】顶点数:8 边数:9第一条边的信息:由12 ,权值为3第二条边的信息:由13 ,权值为5第三条边的信息:由26 ,权值为7第四条边的信息:由67 ,权值为5第五条边的信息:由57 ,权值为8第
15、六条边的信息:由35 ,权值为4第七条边的信息:由34 ,权值为6第八条边的信息:由48 ,权值为9第九条边的信息:由78 ,权值为6分析所得关键路径为:13578,时间长度为23;由程序所得:关键活动为从1到 3的关键路径是 5,发生时间为:0从3到 5的关键路径是 4,发生时间为:5从5到 7的关键路径是 8,发生时间为:9从7到 8的关键路径是 6,发生时间为:17分析与程序所得相同。六、实习日志【第一天】 拿到的题目是求做一个工程的关键路径,此题目是数据结构书上的一个算法,所以在简单的在vc6+里面将一些基本以后要用到的头文件、宏定义、各结构体等先建立好,然后根据题目的要求开始看书,整
16、体想此题的思路是什么?如何开始去做,以及做的每一步骤是什么? 求关键路径要用到栈的知识、所以在今天先编写了进栈和出栈的函数,以便今后拓扑排序函数和求关键路径函数的使用,也初步学习了如何用邻接表构造一个有向图。【第二天】 继续昨天还未完成的函数用邻接表构造一个有向图。 看书以及在网上找了一些代码先明白了如何用邻接表构造一个有向图的算法,先输入顶点值,也就是头结点,这是一个数组,再输入边的值,这是每个头结点引出的一个链式结构,在构造图时,还要编写判断输入非法或者错误的语句,使得程序健硕性。 之后进行拓扑排序的程序算法,要用到判断顶点入度的函数,也要用到判栈空的函数,所以在前面的函数上先将这两个函数
17、补上去。然后开始对拓扑排序函数就行研究。【第三天】 今日对拓扑函数进行了研究和学习,在明白了其排序原理后,将书上的伪代码进行了研读,以及如何可以将伪代码写成可执行的函数,其中要用到之前准备好的栈结构,而在写完代码后,运行的结果总是有问题,例如:error C2115: function : incompatible types和warning C4024: InitStack : different types for formal and actual parameter 1等问题,在经过开始自己的摸索与后来问老师的回答,我补充自己在C语言方面的漏洞,在函数调用的时候,我们不仅要靠调用的参数
18、,还要考虑是实参还是形参,以及调用结束后是否需要返回值改变等等问题。 在解决了传值问题之后开始解决拓扑排序问题,也对其中要用到的函数进行了编写,例如LocateVex(返回顶点v在图顶点向量中的位置)函数的编写。【第四天】 通过昨天对拓扑函数的编写,今天的任务主要是关键路径的编写,也是这个程序的最后一个函数。 通过看书上的伪代码,写对其进行算法进行了了解,再将其改为可执行的C语言代码,关键路径要用到昨天编写的拓扑排序,通过拓扑排序算出各个顶点的最早发生时间,在顺便将其按拓扑排序放在一个栈里面,在关键路径的算法中则刚好用到已排好序的栈,可以算出最迟发生时间。则最早发生时间与最迟发生时间相等则是关
19、键路径。 通过将最后一个函数编写完,除了文件方面的知识,基本已经完成了雏形,并对其进行了调试。【第五天】 相对已经初具模型的程序进行调试,发现了好多错误,以前都只是按右键点击,在函数里设置断点,然后按F10来进行对程序的调试,而今天也学会了另一种方式的调试,用这个图标在有问题的地方设置上断点,然后可以点击这个图标对程序进行调试,也同时明白了这几个图标的含义,表示函数,:跳到函数里面调试,:跳过当前函数,:跳出这个函数。 对程序进行了一些改正,开始着手文件方面的知识,由于当时学的时候几乎等于没有学,所以今天只是在看书,并将书上所写的文件函数代码输入到Visual C+ 6.0进行练习。【第六天】
20、 由于题目要求是文件输入和键盘输入两种方式,所以就对其进行文件输入的编写,文件读入有以下几种方式:fgetc();是从指定的文件中读一个字符,fgets();从指定的文件中读一个字符串到字符数组中,fread();用于读出一组数据,返回已读出数据的个数,fscanf();其功能与键盘输入的scanf();功能差不多,只是对象是文件。 为了将文件中的数据读出并构建有向图的邻接表,所以用哪一个读出函数比较好,并且其函数有了,如何实现用读出的数据来建立有向图,开始想着用fgets();获得一行,然后用每行的数据去构建邻接表,但是对输入顶点和权值那一项却不知道如何进行,所以放弃了此种方法,最后选定为f
21、scnaf();函数来输入数据,在和老师共同探讨之下,早上基本完成了其文件的输入问题。 下午,开始实行最后一个问题:文件输出问题。文件的输出也有好几个,比如fputc();fputs();fwrite();以及fprintf();对于输出,老师的方法让我大开眼见,也知道了fprintf();不仅仅在括号里必须输入三项,只要两项就好了,也就是说仅仅只要将曾经的键盘输出的printf();改成fprintf();且在里面加入文件指针就可以将其内容打印在文件中。【第七天】 对程序进行整体的调试和测试,输入正确和错误的程序,看程序是否正确,如不正确则对其进行修改。 对程序的输出界面进行设计,如何简单大
22、方得体,是客户看着舒心则是我的目的,也在周围看了下其他同学的输出界面,对其进行学习,学会了如何使输出界面的屏幕颜色进行更改,也顺便将自己的界面改成一个柔和的界面。【第八天】 在做完整个界面的设计后,并输出格式的错误,使其界面依旧完整统一化。 对已经完工的程序看是否还有改进的地方,也通过输入错误的值,更加知道程序的一些漏洞,比如在输入错误的后,是否可以更具客户的要求而不退出系统,以及在选择了文件输入后是否还可以根据客户的要求打印在屏幕上,或者选择键盘输入后是否可以根据客户的要求在打印在文件里。今天便是进行对程序漏洞的修改。以及使程序更加人性化。【第九天】 对程序的流程进行分析并画出流程图,也在观
23、看了几名同学的成果展示之后,又对自己的程序进行了修改,为了更好的满足客户的要求,又添加了一项功能,在每次结果出来后,问下客户是否需要继续,是则继续进行程序,不是则退出。也是看了几个同学的系统,自己也添加了清屏的功能。 并在下午开始写实习论文。【第十天】 我们今天早上实习答辩。由于昨天晚上突然想到文件输入构建图,如果文件数据是错误的,如何解决,并且在昨天晚上解决到两点仍无法解决,所以今天下午来问老师将代码作了进一步的改进。七、实习总结 通过这次的实习,自己的编程能力有了一定的提升,不仅仅是对程序的编写能力,也是对程序各方面考虑的能力都有很大的提高。 我的题目是求关键路径,是这学期刚学到的新知识,
24、要用图的结构来解决问题。其中就有有向图的建立,以及拓扑排序,关键路径的算法。 题目还要求用到键盘输入和文件输入两种方式,所以则需要用到去年学的文件方面的知识,文件对于我们来说,还是一个盲点,所以通过这一次的实习,使我对于文件的掌握有了更一步加深。 在程序基本写好后,调试和测试则成了重点,以前很少用到调试,甚至也不太会,而通过这一次的实习,当遇到问题则会自己先通过调试解决,如果调试之后还解决不了了,则会向老师请教,而老师往往会给我们一些更好的以及更简单的方法去实现相应的功能。 在最后几天了,不仅仅是对算法实现以及编程提高了,还对于如何使函数更加健硕进行了深度思考,教会了我要对问题要全面分析,以及对于问题会出现的漏洞也要进行全面分析,并且将漏洞都补好。 这次的实习使我的思路变得更加的开阔,也使得编程能力得到了提高,感谢这一次的实习。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1