关键路径(C语言简单实现)

本文介绍了关键路径算法的原理,通过一个学生做作业的例子解释了最早开始时间和最晚开始时间的概念,阐述了如何找到关键活动和关键路径。并提供了C语言实现关键路径算法的概述及算法复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键路径(C语言简单实现)

本文参考自《大话数据结构》,对关键路径的理解参考自:https://www.jianshu.com/p/1857ed4d8128

在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,我们称之为AOE 。我们把AOE网中没有入边的顶点称为始点或源点,没有出边的顶点称为终点或汇点。

尽管AOE网和AOV网都是用来对工程建模的,但它们还是有很大的不同,主要体现在AOV网是顶点表示活动的网,只描述活动之间的制约关系,而AOE网是用边表示活动的网,边上的权值表示活动持续的时间。

关键路径算法原理

​ 为了讲清楚求关键路径的算法,我还是来举个例子。假设一个学生放学回家,除掉吃饭、洗漱外,到睡觉前有四小时空闲,而家庭作业需要两小时完成。不同的学生会有不同的做法,抓紧的学生,会在头两小时就完成作业,然后看看电视、读读课外书什么的;但也有超过一半的学生会在最后两小时才去做作业,要不是因为没时间,可能还要再拖延下去。
​ 这里做家庭作业这活动的最早开始时间是四小时的开始,可以理解为0,而最晚开始时间是两小时之后马上开始,不可以再晚,否则就是延迟了,此时可以理解为2。显然,当最早和最晚开始时间不相等时就意味着空闲。
​ 接着,你老妈发现了你拖延的小秘密,于是买了很多的课外习题,要求你四个小时,不许有一丝空闲,省得你拖延或偷懒。此时整个四小时全部被占满,最早开始时间和最晚开始时间都是0,因此它就是关键活动了。
也就是说,我们只需要找到所有活动的最早开始时间和最晚开始时间,并且比较它们,如果相等就意味着此活动是关键活动,活动间的路径为关键路径。如果不等,则就不是。

我们把路径上各个活动所持续的时间之和称为路径长度,从源点到汇点具有最大长度的路径叫关键路径,在关键路径上的活动叫关键活动

几个关键参数

  1. 事件的最早发生时间etv:即顶点vk的最早发生时间;
  2. 事件的最晚发生时间ltv:即顶点vk的最晚发生时间,也就是每个顶点对应的事件最晚需要开始的时间,超出此时间将会延误整个工期;
  3. 活动的最早开工时间ete:即弧ak的最早发生时间;
  4. 活动的最晚开工时间lte:即弧ak的最晚发生时间,也就是不推迟工期的最晚开工时间。

可以由1和2求的3和4,然后再根据ete[k]是否与lte[k]相等来判断ak是否是关键活动

关键路径算法

与拓扑排序时邻接表结构不同的地方在于,弧链表增加了weight域,用来存储弧的权值。

求事件的最早发生时间etv的过程,就是我们从头到尾找拓扑的过程,因此,在求关键路径之前,需要先调用一次拓扑序列算法的代码来计算etv和拓扑序列列表。为此,我们先在程序开始处声明几个全局变量。

int *etv, *ltv;	//事件最早发生时间和最迟发生时间数组
int *stack2;	//用于存储拓扑序列的栈
int top2;	//用于stack2的指针

下面是改进过的求拓扑序列算法:

Status TopologicalSort(GraphAdjList GL){
   
	EdgeNode *e;
	int i, k, gettop;
	int top = 0;	//用于栈指针下标
	int count = 0;	//用于同级输出顶点的个数
	int *stack;	//建栈将入度为0的顶点入栈
	stack = (int*)malloc(GL->numVertexes * sizeof(int));
	for(i=0;i<GL->numVertexes;i++)
		if(0 == GL->adjList[i].in)
			stack[++top] = i;
	top2 = 0;	//初始化为0
	etv = (int*)malloc(GL->numVertexes*sizeof(int));	//事件最早发生时间
	for(i=0;i<GL->numVertexes;i++)
		etv[i] = 0;	//初始化为0
	stack2 = (int*)malloc(GL->numVertexes*sizeof(int));	//初始化
	while(top!=0){
   
		gettop=stack[top--];
		count++;	
		stack2[++top2] = gettop;	//将弹出的顶点序号压入拓扑序列的栈
		for(e=GL->adjList[gettop].firstedge;e;e=e->next){
   
			k = e->adjvex;
			if(!(--GL->adjList[
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值