数据结构与算法——AOE网的关键路径
在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,称之为AOE网。
AOE网 是建立在子过程之间的制约关系没有矛盾的基础之上,再来分析整个过程需要的开销。所以如果给定AOV网中各顶点活动所需要的时间,则可以转换为AOE网,较为简单的方法就是把每个顶点都拆分成两个顶点,分别表示活动的起点和终点
把上图转换成一般的AOE图如下:
看图分析:
上图为AOE网和AOE转为邻接表结构的存储示意图,其中在边链表中添加weight用于表示活动的权值,数据结构如下;
#include <iostream>
using namespace std;
#define MAXVER 14typedef struct EdgeNode
{
int adjvex;
int weight;
struct EdgeNode *next;
}EdgeNode;typedef struct VertexNode
{
int in;
int data;
EdgeNode* firstedge;
}VertexNode,AdjList[MAXVER];typedef struct
{
AdjList adjList;
int numVertexes, numEdge;
}graphAdjList,*GraphAdjList;
关键路径算法描述
1. 关键路径是AOE网中的最长路径,也是整个工程的最短完成时间;
2. 在关键路径的算法过程中,这两个概念:
a. 事件(顶点)的最早发生时间:前导事件和活动全部完成时间,就是该事件最早发生的时间;
b. 事件的最晚发生时间:逆向思考,后一个事件发生的时间,除去该事件需要活动的时间差,为该事件的最迟发生时间;
3. 如果一个事件的最迟发生时间 等于 该事件的最早发生时间,那么弧就是关键活动了,因为它直接决定了这个工程完成的时间
关键路径实现源码
int *etv, *ltv;
int *stack2;
int top2;bool TopologicalSort(GraphAdjList GL)
{
EdgeNode *e;
int i, k, gettop;
int top = 0;
int count = 0;
int *stack;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;
etv = (int*)malloc(GL->numVertexes*sizeof(int));for (i = 0; i < GL->numVertexes; i++)
etv[i] = 0;stack2 = (int*)malloc(GL->numVertexes * sizeof(int));
while ( top != 0 )
{
gettop = stack[top--];
count++;//将弹出的入度为0的顶点放入stack2中
//有别于stack,这里是遍历的顺序
stack2[++top2] = gettop;for (e = GL->adjList[gettop].firstedge; e; e = e->next)
{
k = e->adjvex;
if (!(--GL->adjList[k].in))
{
stack[++top] = k;
}if ((etv[gettop] + e->weight) > etv[k])
{
etv[k] = etv[gettop] + e->weight;//记录事件发生最早的时间(理解这里的最早含义:是所有前导工作都完成)
}
}
}
if (count < GL->numVertexes)
return false;
else
return true;}
void CriticalPath(GraphAdjList GL)
{
EdgeNode *e;
int i, gettop, k, j;
int ete, lte;
TopologicalSort(GL);ltv = (int*)malloc(GL->numVertexes*sizeof(int));
for ( i=0;i<GL->numVertexes;i++)
{
ltv[i] = etv[GL->numVertexes - 1];//初始化为最后一个顶点发生的最小时间
}while ( top2 != 0 )
{
gettop = stack2[top2--];//将拓扑序列出栈,注意这里是按照拓扑排序的逆序for (e = GL->adjList[gettop].firstedge;e;e = e->next)
{//求各顶点事件的最迟发生时间ltv值
k = e->adjvex;
//这里利用尾顶点的最迟发生时间 - 当前弧的权值来得到该顶点的最迟发生时间
if (ltv[k] - e->weight < ltv[gettop])
{
ltv[gettop] = ltv[k] - e->weight;
}
}}
for (j = 0; j < GL->numVertexes;j++)
{for (e = GL->adjList[j].firstedge;e;e = e->next)
{
k = e->adjvex;
ete = etv[j];//最早发生时间
lte = ltv[k] - e->weight;//最迟发生时间if (ete == lte)
{
cout << "< " << GL->adjList[j].data << "," << GL->adjList[k].data << " > " << endl;
}}
}
}