数据结构课程设计:拓扑排序和关键路径复习进程

合集下载

数据结构(牛小飞)3 拓扑排序

数据结构(牛小飞)3 拓扑排序

2021/8/5
25
5
拓扑排序-定义
拓扑排序是对有向无圈图的顶点的一种排序,使 得如果存在一条从vi到vj的路径,那么在排序中vj 就出现在vi的后面。
✓ 显然,如果图中含有圈,那么拓扑排序是不可能的, 因为对于圈上的两个顶点v和w,v优先于w同时w又优 先于v。
2021/8/5
6
拓扑排序-举例
B
A
D
C
不能求得它的拓扑有序序列。
// 对尚未访问的顶点调用DFS
}
while(!Empty(S)) //输出拓扑排序的结果
System.out.print(S.pop());
} 2021/8/5
21
拓扑排序-方法2
void DFS-T(int v) { // 从顶点v出发,深度优先搜索遍历连通图 vertexs[v].visited = true; for(w=FirstAdjVex(v);w>=0; w=NextAdjVex(v,w)) { if (!vertexs[w].visited) DFS-T(w); } // 对v的尚未访问的邻接顶点w递归调用DFS-T S.push(v); //顶点v的DFS函数执行完毕
q.enqueue(v);
while (!q.isEmpty( ) { //如果队列非空
…………
}
if (counter!=NUM_VERTICES) //有圈
throw new CycleFoundException( );
}
2021/8/5
15
拓扑排序-方法1
void topsort( ) throws CycleFoundException { …….
} // DFS-T

《数据结构》课程标准

《数据结构》课程标准

《数据结构》课程标准学时:72学时(其中:讲课学时:36 上机学时:36 )先修课程:高等数学、C语言程序设计后续课程:软件开发相关的应用性课程(Android应用开发、软件工程等)适用专业:软件技术、移动应用开发、软件与信息服务等开课部门:信息工程与大数据学院一、课程的性质《数据结构》是面向软件技术相关专业的一门专业基础课,课程要求:熟练掌握线性表、栈和队的存储结构及基本操作,并能在相应的应用中正确地选用,培养学生用链式结构编写程序的能力;了解串和广义表的定义和存储结构;掌握数组的存储结构,熟悉稀疏矩阵的两种压缩存储方法的特点及适用范围;了解树的存储结构及特点,掌握二叉树和图的存储结构及其相应算法,培养学生用非线性结构解决实际问题的能力;掌握各种查找、排序方法,培养学生灵活应用已有排序方法的能力,开拓思路编写新的排序算法。

二、课程设计理念数据结构是计算机存储、组织数据的方式。

数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。

精心选择的数据结构可以带来更高的运行或存储效率,数据结构往往同高兴的检索算法和索引技术有关。

1、课程地位理念在许多类型的程序设计中,数据结构的选择是一个基本的设计考虑因素。

许多大型的构造经验表明,系统实现的困难程度和系统构造的质量都严重的依赖于是否选择了最优的数据结构。

许多时候,确定了数据结构后,算法就容易得到了。

有些时候事情也会反过来,我们根据特定算法来选择数据结构与之适应。

不论哪种情况,选择合适的数据结构都是非常重要的。

选择了数据结构,算法随之确定,是数据而不是算法是系统构造的关键因素。

2、课程学情理念本课程开设在嵌入式系统工程专科第一学期,学生在学习本课程前已具备计算机基础、C语言基础等知识,本课程力图让学生学会在C语言环境下,运用面向对象的思想编写规范的代码,实现经典的数据结构和算法。

熟悉常用的数据结构和算法,使学生初步具备一个优秀的软件开发人员所应有的基本能力。

计算机考研各个科目的复习思路

计算机考研各个科目的复习思路

计算机考研各个科目的复习思路计算机考研各个科目的复习思路1、“数据结构”复习思路:“数据结构”的复习应以“线性结构→树型结构→图型结构→查找表→排序算法”为主线进行复习,重点在“线性结构”、“图”和“排序”三个部分,“线性结构”、“树”和“图”侧重基础概念、基础原理和基础方法的掌握,“图”、“查找”和“排序”则侧重具体应用的考核。

2、“计算机组成原理”复习思路:“计算机组成原理”按照冯·诺伊曼计算机5部分组成结构为大块进行复习。

“计算机系统概述”和“数的表示和运算”重点在于基本概念的掌握,没有具体应用。

而“存储器的层次结构”,“指令系统”,“中央处理器”,“总线”和“输入输出系统”部分除了掌握基本原理,基本方法外,重点掌握应用。

3、“操作系统”复习思路操作系统”复习思路:“操作系统”按照操作系统的基本功能为主线进行复习,即“进程管理”,“内存管理”,“文件管理”和“输入输出管理”。

其中重点部分在“进程管理”和“内存管理”。

一、重难点解析和复习建议统考大纲对数据结构的考查目标定位为掌握数据结构的基本概念、基本原理和基本方法,掌握数据的逻辑结构、存储结构以及基本操作的实现;能够对算法进行基本的时间复杂度和空间复杂度的分析;能够运用数据结构的基本原理和方法进行问题的分析求解,具备采用C、C++或JAVA语言设计程序与实现算法的能力。

当然,考生也不必因此而专门复习一遍C或C++程序设计,毕竟复习时间有限,而且数据结构要求的重点在于算法设计的能力,而不是编写代码的能力,因此,只要能用类似伪代码的形式把思路表达清楚就行,不用强求写出一个没有任何语法错误的程序。

下面我们来解析一下知识点:线性表这一章里面的知识点不多,但要做到深刻理解,能够应用相关知识点解决实际问题。

链表上插入、删除节点时的指针操作是选择题的一个常考点,诸如双向链表等一些相对复杂的链表上的操作也是可以出现在综合应用题当中的。

栈、队列和数组可以考查的知识点相比链表来说要多一些。

数据结构课设——有向图的深度、广度优先遍历及拓扑排序

数据结构课设——有向图的深度、广度优先遍历及拓扑排序

数据结构课设——有向图的深度、⼴度优先遍历及拓扑排序任务:给定⼀个有向图,实现图的深度优先, ⼴度优先遍历算法,拓扑有序序列,并输出相关结果。

功能要求:输⼊图的基本信息,并建⽴图存储结构(有相应提⽰),输出遍历序列,然后进⾏拓扑排序,并测试该图是否为有向⽆环图,并输出拓扑序列。

按照惯例,先上代码,注释超详细:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#pragma warning(disable:4996)#define Max 20//定义数组元素最⼤个数(顶点最⼤个数)typedef struct node//边表结点{int adjvex;//该边所指向结点对应的下标struct node* next;//该边所指向下⼀个结点的指针}eNode;typedef struct headnode//顶点表结点{int in;//顶点⼊度char vertex;//顶点数据eNode* firstedge;//指向第⼀条边的指针,边表头指针}hNode;typedef struct//邻接表(图){hNode adjlist[Max];//以数组的形式存储int n, e;//顶点数,边数}linkG;//以邻接表的存储结构创建图linkG* creat(linkG* g){int i, k;eNode* s;//边表结点int n1, e1;char ch;g = (linkG*)malloc(sizeof(linkG));//申请结点空间printf("请输⼊顶点数和边数:");scanf("%d%d", &n1, &e1);g->n = n1;g->e = e1;printf("顶点数:%d 边数:%d\n", g->n, g->e);printf("请输⼊顶点信息(字母):");getchar();//因为接下来要输⼊字符串,所以getchar⽤于承接上⼀条命令的结束符for (i = 0; i < n1; i++){scanf("%c", &ch);g->adjlist[i].vertex = ch;//获得该顶点数据g->adjlist[i].firstedge = NULL;//第⼀条边设为空}printf("\n打印顶点下标及顶点数据:\n");for (i = 0; i < g->n; i++)//循环打印顶点下标及顶点数据{printf("顶点下标:%d 顶点数据:%c\n", i, g->adjlist[i].vertex);}getchar();int i1, j1;//相连接的两个顶点序号for (k = 0; k < e1; k++)//建⽴边表{printf("请输⼊对<i,j>(空格分隔):");scanf("%d%d", &i1, &j1);s = (eNode*)malloc(sizeof(eNode));//申请边结点空间s->adjvex = j1;//边所指向结点的位置,下标为j1s->next = g->adjlist[i1].firstedge;//将当前s的指针指向当前顶点上指向的结点g->adjlist[i1].firstedge = s;//将当前顶点的指针指向s}return g;//返回指针g}int visited[Max];//标记是否访问void DFS(linkG* g, int i)//深度优先遍历{eNode* p;printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已访问过的顶点visited值改为1p = g->adjlist[i].firstedge;//p指向顶点i的第⼀条边while (p)//p不为NULL时(边存在){if (visited[p->adjvex] != 1)//如果没有被访问DFS(g, p->adjvex);//递归}p = p->next;//p指向下⼀个结点}}void DFSTravel(linkG* g)//遍历⾮连通图{int i;printf("深度优先遍历;\n");//printf("%d\n",g->n);for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问{DFS(g, i);//调⽤DFS函数}}}void BFS(linkG* g, int i)//⼴度优先遍历{int j;eNode* p;int q[Max], front = 0, rear = 0;//建⽴顺序队列⽤来存储,并初始化printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已经访问过的改成1rear = (rear + 1) % Max;//普通顺序队列的话,这⾥是rear++q[rear] = i;//当前顶点(下标)队尾进队while (front != rear)//队列⾮空{front = (front + 1) % Max;//循环队列,顶点出队j = q[front];p = g->adjlist[j].firstedge;//p指向出队顶点j的第⼀条边while (p != NULL){if (visited[p->adjvex] == 0)//如果未被访问{printf("%c ", g->adjlist[p->adjvex].vertex);visited[p->adjvex] = 1;//将该顶点标记数组值改为1rear = (rear + 1) % Max;//循环队列q[rear] = p->adjvex;//该顶点进队}p = p->next;//指向下⼀个结点}}}void BFSTravel(linkG* g)//遍历⾮连通图{int i;printf("⼴度优先遍历:\n");for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问过{BFS(g, i);//调⽤BFS函数}}}//因为拓扑排序要求⼊度为0,所以需要先求出每个顶点的⼊度void inDegree(linkG* g)//求图顶点⼊度{eNode* p;int i;for (i = 0; i < g->n; i++)//循环将顶点⼊度初始化为0{g->adjlist[i].in = 0;}for (i = 0; i < g->n; i++)//循环每个顶点{p = g->adjlist[i].firstedge;//获取第i个链表第1个边结点指针while (p != NULL)///当p不为空(边存在){g->adjlist[p->adjvex].in++;//该边终点结点⼊度+1p = p->next;//p指向下⼀个边结点}printf("顶点%c的⼊度为:%d\n", g->adjlist[i].vertex, g->adjlist[i].in);}void topo_sort(linkG *g)//拓扑排序{eNode* p;int i, k, gettop;int top = 0;//⽤于栈指针的下标索引int count = 0;//⽤于统计输出顶点的个数int* stack=(int *)malloc(g->n*sizeof(int));//⽤于存储⼊度为0的顶点for (i=0;i<g->n;i++)//第⼀次搜索⼊度为0的顶点{if (g->adjlist[i].in==0){stack[++top] = i;//将⼊度为0的顶点进栈}}while (top!=0)//当栈不为空时{gettop = stack[top--];//出栈,并保存栈顶元素(下标)printf("%c ",g->adjlist[gettop].vertex);count++;//统计顶点//接下来是将邻接点的⼊度减⼀,并判断该点⼊度是否为0p = g->adjlist[gettop].firstedge;//p指向该顶点的第⼀条边的指针while (p)//当p不为空时{k = p->adjvex;//相连接的顶点(下标)g->adjlist[k].in--;//该顶点⼊度减⼀if (g->adjlist[k].in==0){stack[++top] = k;//如果⼊度为0,则进栈}p = p->next;//指向下⼀条边}}if (count<g->n)//如果输出的顶点数少于总顶点数,则表⽰有环{printf("\n有回路!\n");}free(stack);//释放空间}void menu()//菜单{system("cls");//清屏函数printf("************************************************\n");printf("* 1.建⽴图 *\n");printf("* 2.深度优先遍历 *\n");printf("* 3.⼴度优先遍历 *\n");printf("* 4.求出顶点⼊度 *\n");printf("* 5.拓扑排序 *\n");printf("* 6.退出 *\n");printf("************************************************\n");}int main(){linkG* g = NULL;int c;while (1){menu();printf("请选择:");scanf("%d", &c);switch (c){case1:g = creat(g); system("pause");break;case2:DFSTravel(g); system("pause");break;case3:BFSTravel(g); system("pause");break;case4:inDegree(g); system("pause");break;case5:topo_sort(g); system("pause");break;case6:exit(0);break;}}return0;}实验⽤图:运⾏结果:关于深度优先遍历 a.从图中某个顶点v 出发,访问v 。

数据结构之拓扑排序算法详解

数据结构之拓扑排序算法详解

数据结构之拓扑排序算法详解拓扑排序算法是一种常用于有向无环图(DAG)的排序算法,它可以将图中的顶点按照一定的顺序进行排序,使得图中任意一条有向边的起点在排序结果中都排在终点的前面。

在实际应用中,拓扑排序算法常用于解决任务调度、依赖关系分析等问题。

本文将详细介绍拓扑排序算法的原理、实现方法以及应用场景。

### 一、拓扑排序算法原理拓扑排序算法的原理比较简单,主要包括以下几个步骤:1. 从DAG图中选择一个入度为0的顶点并输出。

2. 从图中删除该顶点以及以该顶点为起点的所有有向边。

3. 重复步骤1和步骤2,直到图中所有顶点都被输出。

### 二、拓扑排序算法实现下面以Python语言为例,给出拓扑排序算法的实现代码:```pythondef topological_sort(graph):in_degree = {v: 0 for v in graph}for u in graph:for v in graph[u]:in_degree[v] += 1queue = [v for v in graph if in_degree[v] == 0] result = []while queue:u = queue.pop(0)result.append(u)for v in graph[u]:in_degree[v] -= 1if in_degree[v] == 0:queue.append(v)if len(result) == len(graph):return resultelse:return []# 测试代码graph = {'A': ['B', 'C'],'B': ['D'],'C': ['D'],'D': []}print(topological_sort(graph))```### 三、拓扑排序算法应用场景拓扑排序算法在实际应用中有着广泛的应用场景,其中包括但不限于以下几个方面:1. 任务调度:在一个任务依赖关系图中,拓扑排序可以确定任务的执行顺序,保证所有任务按照依赖关系正确执行。

信息学奥赛一本通 第4章 第7节 拓扑排序与关键路径(C++版)

信息学奥赛一本通 第4章  第7节 拓扑排序与关键路径(C++版)

拓扑排序算法
【参考程序】 //gentree #include<cstdio> #include<iostream> using namespace std; int a[101][101],c[101],r[101],ans[101]; int i,j,tot,temp,num,n,m; int main() { freopen("gentree.in","r",stdin); freopen("gentree.out","w",stdout); cin >> n; for (i = 1; i <= n; i++) { do { cin >> j; if (j !=0 ) { c[i]++; //c[i]用来存点i的出度 a[i][c[i]] = j; r[j]++; //r[i]用来存点i的入度。 } } while (j != 0); }
拓扑排序算法
【数据规模】 80%的数据满足n<=1000,m<=2000;100%的数据满足n<=10000,m<=20000。 【算法分析】 首先构图,若存在条件“a的钱比b多”则从b引一条有向指向a;然后拓扑排序, 若无法完成排序则表示问题无解(存在圈);若可以得到完整的拓扑序列,则按序 列顺序进行递推: 设f[i]表示第i个人能拿的最少奖金数; 首先所有f[i]=100(题目中给定的最小值); 然后按照拓扑顺序考察每个点i,若存在有向边(j,i),则表示f[i]必须比f[j] 大,因此我们令f[i] = Max { f[i] , f[j]+1 }即可; 递推完成之后所有f[i]的值也就确定了,而答案就等于f[1]+…+f[n]。

《数据结构课程设计》指导书

《数据结构课程设计》指导书

《数据结构》课程设计指导书沈阳理工大学.信息学院2013.11.1一.目的与意义软件设计能力对计算机专业的学生是很重要。

通过数据结构的学习,使学生对软件编程能力有一定的提高。

数据结构课程设计是锻炼学生在进一步掌握模块化、结构化程序设计的方法的同时,培养学生运用已学知识分析问题、解决问题及编写实用程序的能力,通过对线性化、层次化、网络化数据结构的了解进一步掌握自然数据的结构方式及组织方式,让学生深入体会存储在计算机中的数据及程序中如何运用数据实现编程。

主要目的如下:1.通过本课程设计使学生对面向对象的设计过程有初的认识,并对面向对象的高能语言的学习打下基础,2.通过不同类型的程序设计使学生进一步掌握数据的几种不同的组织和存储方式,为高级编程做准备,3.为专业课的深入学习和毕业设计打基础二.任务和要求分析每一组题目,按要求完成相应的题目:1.题目参照附录中《数据结构课程设计》题目选题。

2. 要求:1)对相应的题目进行算法设计2)编写源代码3)上机调试4)显示调试结果5)写出实验总结3.课程设计说明书设计完成后,将自己选定的题目按上述要求完成课程设计说明书。

课程设计说明书内容包含:题目、要求、初步设计(可以是流程图、功能模块图)、详细设计、程序代码、测试数据、运行结果、遇到的问题及总结几部分。

三.进度安排设计总学时为2周第一周:查阅资料、小组讨论、进行模块划分写出分析报告,画N-S结构化框图,编写程序清单,上机调试.第二周周四、五:验收(计算机机房),并将课程设计报告交上来.四.考核标准与成绩评定方式成绩评定有如下几项参考:1.初步设计内容的考核:是否有查阅资料能力?是否有设计思想?2.程序编码能力调试能力的考核:程序是否清晰、易读?在技算计上是否可独立完成程序的调试,是否熟练?3.说明书质量的考核:设计结构是否合理?叙述是否正确?方案是否可行?4.答辩:设计结果的调试能力,对自己设计是否熟练?5.出勤率极平时表现的考核:出勤超过2次不到者成绩为不及格。

课次21——第七章03拓扑排序和关键路径

课次21——第七章03拓扑排序和关键路径
拓扑序列:有向图D的一个顶点序列称作一个拓扑序列,如果该 序列中任两顶点v 、u ,若在D中v是u前趋,则在序列中v也是u 前趋。
对有向图进行如下操作:按照有向图给出的次序关系,将图 中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶 点,则可以人为加上任意的次序关系。由此所得顶点的线性序列 称之为拓扑有序序列。
v3 v5
v9
v8
v4
v6
13 2020/8/4
7.5.2 关键路径(4)
在AOE网络中, 有些活动顺序进行,有些活动并行进行。
从源点到各个顶点,以至从源点到汇点的有向路径可能不止 一条。这些路径的长度也可能不同。完成不同路径的活动所 需的时间虽然不同,但只有各条路径上所有活动都完成了, 整个工程才算完成。
例:
C0
C1
C2
C0
C1
C2
C3
C4
C5
(a) 有向无环图
C0
C1
C2
C3
C4
C5
(b) 输出C4
C1
C2
C3
C5
(c) 输出顶点C0
9 2020/8/4
C3
C5
(d) 输出顶点C3
7.5.1拓扑排序(Topological Sort)(7)
C1
C2
C1
C5 (e) 输出顶点C2
C5 (f) 输出顶点C1
因此,完成整个工程所需的时间取决于从源点到汇点的最长 路径长度,即在这条路径上所有活动的持续时间之和。这条 路径长度最长的路径就叫做关键路径(Critical Path)。
子工程所需时间。 问:哪些子工程是“关键工程”? 即:哪些子工程将影响整个工程的完成期限的。
首先了解一些基本概念:
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数据结构课程设计:拓扑排序和关键路径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 //点结点{VertexType 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什么是关键路径关键路径法(Critical Path Method, CPM)最早出现于20世纪50年代,它是通过分析项目过程中哪个活动序列进度安排的总时差最少来预测项目工期的网络分析。

这种方法产生的背景是,在当时出现了许多庞大而复杂的科研和工程项目,这些项目常常需要运用大量的人力、物力和财力,因此如何合理而有效地对这些项目进行组织,在有限资源下以最短的时间和最低的成本费用下完成整个项目就成为一个突出的问题,这样CPM就应运而生了。

对于一个项目而言,只有项目网络中最长的或耗时最多的活动完成之后,项目才能结束,这条最长的活动路线就叫关键路径(Critical Path),组成关键路径的活动称为关键活动。

2.1.2关键路径特点关键路径上的活动持续时间决定了项目的工期,关键路径上所有活动的持续时间总和就是项目的工期。

关键路径上的任何一个活动都是关键活动,其中任何一个活动的延迟都会导致整个项目完工时间的延迟。

关键路径上的耗时是可以完工的最短时间量,若缩短关键路径的总耗时,会缩短项目工期;反之,则会延长整个项目的总工期。

但是如果缩短非关键路径上的各个活动所需要的时间,也不至于影响工程的完工时间。

关键路径上活动是总时差最小的活动,改变其中某个活动的耗时,可能使关键路径发生变化。

可以存在多条关键路径,它们各自的时间总量肯定相等,即可完工的总工期。

关键路径是相对的,也可以是变化的。

在采取一定的技术组织措施之后,关键路径有可能变为非关键路径,而非关键路径也有可能变为关键路径。

2.2关键路径实现过程2.2.1结构选取首先要选取建图的一种算法建立图,有邻接矩阵,邻接表,十字链表,邻接多重表等多种方法,要选取一种适当的方法建立图,才能提高算法效率,降低时间复杂度和空间复杂度。

两个相邻顶点与它们之间的边表示活动,边上的数字表示活动延续的时间。

对于给出的事件AOE网络,要求求出从起点到终点的所有路径,经分析、比较后找出长读最大的路径,从而得出求关键路径的算法,并给出计算机上机实现的源程序。

完成不同路径的活动所需的时间虽然不同,但只有各条路径上所有活动都完成了,这个工程才算完成。

2.2.2具体要解决的问题(1)将项目中的各项活动视为有一个时间属性的结点,从项目起点到终点进行排列;(2)用有方向的线段标出各结点的紧前活动和紧后活动的关系,使之成为一个有方向的网络图;(3)用正推法和逆推法计算出各个活动的最早开始时间,最晚开始时间,最早完工时间和最迟完工时间,并计算出各个活动的时差;(4)找出所有时差为零的活动所组成的路线,即为关键路径;(5)识别出准关键路径,为网络优化提供约束条件;2.2.3算法分析(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>(即从顶点j到k)表示,其持续时间记为dut(<j,k>),则:e(i)=ve(j)l(i)=vl(k)-dut(<j,k>)求ve(i)和vl(j)分两步:1.从ve(1)=0开始向前递推ve(j)=Max{ ve(i)+dut(<i,j>) }<i,j>T, 2<=j<=n其中,T是所有以j为弧头的弧的集合。

2.从vl(n)=ve(n)开始向后递推vl(i)=Min{ vl(j)-dut(<i,j>) }<i,j>S, 1<=i<=n-1其中,S是所有以i为弧尾的弧的集合。

两个公式是在拓扑有序和逆拓扑有序的前提下进行。

2.2.4 算法步骤(1)输入e条弧<j,k>,建立AOE网的存储结构。

(2)从源点v1出发,令ve(1)=0,求个点的最早开始时间ve(j)。

(3)从汇点vn出发,令vl(n)=最大值,求个点的最晚开始时间vl(j)。

(4)由于各结点的最早开始时间已求出来,所以各活动的最早开始时间即(每条弧s(活动)的最早开始时间)就等于该结点的最早开始时间,并由上可同时求出该活动的最晚开始时间l(j)。

(5)具体表达式为:e(i)=ve(j)l(i)=vl(k)-dut(<j,k>)(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)//判断是否为空Status 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) //输出拓扑顺序排序(当拓扑序列存在时)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);来初始化逆拓扑排序的栈。

其次调用CreateALGraph(ALGraph &graph)函数定义和初始化AOE网,调用TopologicalSor t(ALGraph &graph,SqStack &ToPoReverseSort) 函数求拓扑序列和调用PutInfoToPoSort(ToPoSort,graph);函数来输出输出拓扑顺序排序。

然后调用GetVeAndVl(graph,ToPoSort,ToPoReverseSort) 函数求结点和活动的最晚开始时间、最早开始时间并输出。

最后调用Status CriticalPath(ALGraph &graph,SqStack RevSort)函数来求关键活动、关键事件并输出。

4.2初始化模块初始化模块用来初始化图,要求用户自己输入数据,并程序构造AOE 网。

本程序是用自己改进的邻接表来构造AOE网。

见图2-4-2图2-4-2图2-4-34.3求拓扑序列模块利用栈来存储入度为零的结点,然后逐个弹出,来进行与该结点的出度结点来比较,是否符合拓扑排序的规则,最后用ToPoReverseSort存放拓扑逆序序列来完成整个拓扑排序。

见图2-4-34.4求最晚开始时间和最早开始时间模块(包括结点和活动的最早和最晚开始时间)见图2-4-4图2-4-4 4.5关键活动和关键事件见图2-4-5N图2-4-54.6输出模块输出相应结点的信息,拓扑序列,以及事件的最早开始时间和最晚开始时间,输出相应的活动的最早开始时间和最晚开始时间,关键活动以及关键事件。

5 测试分析5.1测试内容求的关键路径为:程序输入部分:求拓扑序列部分求结点和活动的最早开始时间和最晚开始时间输出图中的关键事件和关键活动(关键路径)测试关键路径结果:5.2回路测试结果分析:结果完全符合所求,但是输出的方面不够完美,并且自我感觉程序所使用的空间比较大,算法复杂度较高,所以效率比较低下,当程序输入存在有环的时候,程序没有发生任何错误,直接输出“图存在有环”然后退出程序。

由此可见本程序计划实施到完工比较顺利的完成了,并且在程序测试中能够得到预期的结果出来,不过唯一不满意的是程序过于复杂化,使用的太多的空间,致使程序成为一个缺陷。

相关文档
最新文档