前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法:求解AOE网的关键路径

算法:求解AOE网的关键路径

作者头像
s1mba
发布2018-01-15 15:29:35
1.5K0
发布2018-01-15 15:29:35
举报
文章被收录于专栏:开发与安全开发与安全

前面我们简要地介绍了AOE网和关键路径的一些概念,本文接着对求解关键路径程序的主要函数进行分析。现有一AOE网图如图7-9-4所示,我们使用邻接表存储结构,注意与拓扑排序时邻接表结构不同的地方在于,这里弧表结点增加了weight域,用来存储弧的权值。

求解事件的最早发生时间etv的过程,就是我们从头至尾找拓扑序列的过程,因此在求关键路径之前,需要先调用一次拓扑序列算法的代码来计算etv 和 拓扑序列列表,我们针对前面讲过的AOV网与拓扑排序的程序进行改进,代码如下(参考《大话数据结构》):

代码语言:cpp
复制
/* 拓扑排序,若GL无回路,则输出拓扑排序序列并返回1,若有回路返回0。 */
bool TopologicalSort(GraphAdjList GL)
{
    EdgeNode *pe;
    int i, k, gettop;
    int top = 0;/* 用于栈指针下标  */
    int count = 0;/* 用于统计输出顶点的个数  */
    /* 建栈将入度为0的顶点入栈  */
    int *stack = (int *)malloc(GL->numVertexes * sizeof(int));

    for (i = 0; i < GL->numVertexes; i++)
        if (0 == GL->adjList[i].in)
            stack[++top] = i;/* 将入度为0的顶点入栈 */

    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));

    cout << "TopologicalSort ..." << endl;

    while (top != 0)
    {
        gettop = stack[top--];
        cout << GL->adjList[gettop].data << " -> ";
        count++;  /* 输出i号顶点,并计数 */

        stack2[++top2] = gettop; /* 将弹出的顶点序号压入拓扑序列的栈 */

        for (pe = GL->adjList[gettop].firstedge; pe; pe = pe->next)
        {
            k = pe->adjvex;
            /* 将i号顶点的邻接点的入度减1,如果减1后为0,则入栈 */
            if (!(--GL->adjList[k].in))
                stack[++top] = k;
            /* 求各顶点事件的最早发生时间etv值 */
            if ((etv[gettop] + pe->weight) > etv[k])
                etv[k] = etv[gettop] + pe->weight;
        }
    }
    cout << endl;
    if (count < GL->numVertexes)
        return false;
    else
        return true;
}

在程序开始处我们声明了几个全局变量:

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

其中stack2用来存储拓扑序列,以便后面求关键路径时使用。

上面的拓扑排序函数中除了增加了第12~19行,29行,38~39行,其他跟前面讲过的AOV网与拓扑排序没什么区别。

第12~19行初始化全局变量etv数组、top2和stack2的过程。第29行就是将本来要输出的拓扑序列压入全局栈stack2中。第38~39行很关键,是求etv数组的每一个元素的值,具体求值办法参见AOE网和关键路径

下面来看求关键路径的算法代码。

代码语言:cpp
复制
/* 求关键路径,GL为有向网,输出G的各项关键活动 */
void CriticalPath(GraphAdjList GL)
{
    EdgeNode *pe;
    int i, j, k, gettop;
    int ete, lte;/* 声明活动最早发生时间和最迟发生时间变量 */
    TopologicalSort(GL);/* 求拓扑序列,计算数组etv和stack2的值 */

    ltv = (int *)malloc(GL->numVertexes * sizeof(int)); /* 事件最早发生时间数组 */

    for (i = 0; i < GL->numVertexes; i++)
        ltv[i] = etv[GL->numVertexes - 1];/* 初始化 */

    cout << "etv :  ";
    for (i = 0; i < GL->numVertexes; i++)
        cout << etv[i] << ' ';
    cout << endl;

    while (top2 != 0)/* 出栈是求ltv */
    {
        gettop = stack2[top2--];
        /* 求各顶点事件的最迟发生时间ltv值 */
        for (pe = GL->adjList[gettop].firstedge; pe; pe = pe->next)
        {
            k = pe->adjvex;
            if (ltv[k] - pe->weight < ltv[gettop])
                ltv[gettop] = ltv[k] - pe->weight;
        }
    }

    cout << "ltv :  ";
    for (i = 0; i < GL->numVertexes; i++)
        cout << ltv[i] << ' ';
    cout << endl;
    /* 求ete,lte和关键活动 */
    for (j = 0; j < GL->numVertexes; j++)
    {
        for (pe = GL->adjList[j].firstedge; pe; pe = pe->next)
        {
            k = pe->adjvex;
            ete = etv[j];/* 活动最早发生时间 */
            lte = ltv[k] - pe->weight;/* 活动最迟发生时间 */
            if (ete == lte) /* 两者相等即在关键路径上 */
                cout << "<v" << GL->adjList[j].data << " - v"
                     << GL->adjList[k].data << "> length: " << pe->weight << endl;
        }
    }
}

函数第7行调用求拓扑序列的函数,执行完毕后,全局数组etv和栈stack2 如图7-9-6所示,top2 = 10,也就是说,对于每个事件的最早发生时间,我们已经计算出来了。

第11~12行初始化全局变量ltv数组,因为etv[9] = 27,所以数组ltv值现在为全27。

第19~29行是计算ltv 数组的循环,具体方法参见AOE网和关键路径

当程序执行到第36行,etv和ltv数组的值如图7-9-9

比如etv[1] = 3, 而ltv[1] = 7,表示如果单位是天的话,哪怕v1整个事件在第7天才开始,也可以保证整个工程的按期完成,可以提前v1事件开始时间,但最早也得第3天开始。

第36~47行是求另两个变量,活动最早开始时间ete和活动最晚开始时间lte,并对相同下标的它们进行比较。两重循环嵌套是对邻接表的顶点和每个顶点的弧表遍历,具体方法参见AOE网和关键路径,举例来说,如图7-9-10,当j = 0时,当k = 2, ete = lte, 表示

弧<v0, v2> 是关键路径,因此打印;当k = 1, ete != lte, 故弧<v0, v1> 不是关键路径。

j = 1 一直到 j = 9为止,做法是完全相同的,最后输出的结果如下图,最终关键路径如图7-9-11所示。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2013-05-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档