【大话数据结构C语言】50 关键路径

举报
CodeAllen 发表于 2021/10/29 23:52:00 2021/10/29
【摘要】 欢迎关注我的公众号是【CodeAllen】,关注回复【1024】获取精品学习资源 程序员技术交流①群:736386324 ,程序员技术交流②群:371394777     上一篇的拓扑排序是解决工作是否顺序进行的问题,但是有时候需要解决工程完成需要的最短时间问题 &nb...

欢迎关注我的公众号是【CodeAllen】,关注回复【1024】获取精品学习资源
程序员技术交流①群:736386324 ,程序员技术交流②群:371394777    

上一篇的拓扑排序是解决工作是否顺序进行的问题,但是有时候需要解决工程完成需要的最短时间问题
 
 
以造车举例子
 
 
请问汽车产造一辆汽车,最短需要多少时间呢?其中生产轮子:0.5天,发动机:3天,底盘:2天,外壳:2天,其他零部件:2天,全部零部件集中到一处:0.5天,组装成车并测试:2天
 
这里边要考虑实际生产是流水线工作,所以这些时间不是简单的相加!
 
关键路径
  • AOE网:在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,我们称之为AOE网(Activity On Edge Network)。
  • 我们把AOE网中没有入边的顶点称为始点或源点,没有出边的顶点称为终点或汇点。
 
 
还是画图看下问题
 
事件2就是时间1完成了,可以进行事件2
 
 
AOV网与AOE网的比较
 
 
 
其中的红色为关键路径
 
现实中情况会更复杂,所以这部分工作就需要找出关键路径
 
 
 
 
代码实践
 
几个关键词
1.事件的最早发生时间etv(earliest time of vertex):即顶点vkvk的最早发生时间
2.事件的最晚发生时间ltv(latest time of vertex):即顶点vkvk的最晚发生时间,也就是每个顶点对应的事件最晚需要开始时间,超出此时间将会延误整个工期
3.活动的最早开工时间ete(earliest time of edge):即弧akak的最早发生时间
4.活动的最晚开工时间lte(latest time of edge):即弧akak的最晚发生时间,也就是不推迟工期的最晚开工时间
 
按图分析
 
 
 
CriticalPath.c

   
  1. // 边表结点声明
  2. typedef struct EdgeNode
  3. {
  4.     int adjvex;
  5.     struct EdgeNode *next;
  6. }EdgeNode;
  7. // 顶点表结点声明
  8. typedef struct VertexNode
  9. {
  10.     int in;         // 顶点入度
  11.     int data;
  12.     EdgeNode *firstedge;
  13. }VertexNode, AdjList[MAXVEX];
  14. typedef struct
  15. {
  16.     AdjList adjList;
  17.     int numVertexes, numEdges;
  18. }graphAdjList, *GraphAdjList;
  19. int *etv, *ltv;
  20. int *stack2;            // 用于存储拓扑序列的栈
  21. int top2;               // 用于stack2的栈顶指针
  22. // 拓扑排序算法
  23. // 若GL无回路,则输出拓扑排序序列并返回OK,否则返回ERROR
  24. Status TopologicalSort(GraphAdjList GL)
  25. {
  26.     EdgeNode *e;
  27.     int i, k, gettop;
  28.     int top = 0;        // 用于栈指针下标索引
  29.     int count = 0;      // 用于统计输出顶点的个数
  30.     int *stack;         // 用于存储入度为0的顶点
  31.     
  32.     stack = (int *)malloc(GL->numVertexes * sizeof(int));
  33.     
  34.     for( i=0; i < GL->numVertexes; i++ )
  35.     {
  36.         if0 == GL->adjList[i].in )
  37.         {
  38.             stack[++top] = i;   // 将度为0的顶点下标入栈
  39.         }
  40.     }
  41.     
  42.     // 初始化etv都为0
  43.     top2 = 0;
  44.     etv = (int *)malloc(GL->numVertexes*sizeof(int));
  45.     for( i=0; i < GL->numVertexes; i++ )
  46.     {
  47.         etv[i] = 0;
  48.     }
  49.     stack2 = (int *)malloc(GL->numVertexes*sizeof(int));
  50.     
  51.     while0 != top )
  52.     {
  53.         gettop = stack[top--];      // 出栈
  54.         // printf("%d -> ", GL->adjList[gettop].data); 
  55.         stack2[++top2] = gettop;    // 保存拓扑序列顺序 C1 C2 C3 C4 .... C9
  56.         count++;                
  57.         
  58.         for( e=GL->adjList[gettop].firstedge; e; e=e->next )
  59.         {
  60.             k = e->adjvex;
  61.             // 注意:下边这个if条件是分析整个程序的要点!
  62.             // 将k号顶点邻接点的入度-1,因为他的前驱已经消除
  63.             // 接着判断-1后入度是否为0,如果为0则也入栈
  64.             if( !(--GL->adjList[k].in) )    
  65.             {
  66.                 stack[++top] = k;
  67.             }
  68.             
  69.             if( (etv[gettop]+e->weight) > etv[k] )
  70.             {
  71.                 etv[k] = etv[gettop] + e->weight;
  72.             }
  73.         }
  74.     }
  75.     
  76.     if( count < GL->numVertexes )   // 如果count小于顶点数,说明存在环
  77.     {
  78.         return ERROR;
  79.     }
  80.     else
  81.     {
  82.         return OK;
  83.     }
  84. }
  85. // 求关键路径,GL为有向图,输出GL的各项关键活动
  86. void CriticalPath(GraphAdjList GL)
  87. {
  88.     EdgeNode *e;
  89.     int i, gettop, k, j;
  90.     int ete, lte;
  91.     
  92.     // 调用改进后的拓扑排序,求出etv和stack2的值
  93.     TopologicalSort(GL);
  94.     
  95.     // 初始化ltv都为汇点的时间
  96.     ltv = (int *)malloc(GL->numVertexes*sizeof(int));
  97.     for( i=0; i < GL->numVertexes; i++ )
  98.     {
  99.         ltv[i] = etv[GL->numVertexes-1];
  100.     }
  101.     
  102.     // 从汇点倒过来逐个计算ltv
  103.     while0 != top2 )
  104.     {
  105.         gettop = stack2[top2--];    // 注意,第一个出栈是汇点
  106.         for( e=GL->adjList[gettop].firstedge; e; e=e->next )
  107.         {
  108.             k = e->adjvex;
  109.             if( (ltv[k] - e->weight) < ltv[gettop] )
  110.             {
  111.                 ltv[gettop] = ltv[k] - e->weight;
  112.             }
  113.         }
  114.     }
  115.     
  116.     // 通过etv和ltv求ete和lte
  117.     for( j=0; j < GL->numVertexes; j++ )
  118.     {
  119.         for( e=GL->adjList[j].firstedge; e; e=e->next )
  120.         {
  121.             k = e->adjvex;
  122.             ete = etv[j];
  123.             lte = ltv[k] - e->weight;
  124.             
  125.             if( ete == lte )
  126.             {
  127.                 printf("<v%d,v%d> length: %d , ", GL->adjList[j].data, GL->adjList[k].data, e->weight );
  128.             }
  129.         }
  130.     }
  131. }

 

文章来源: allen5g.blog.csdn.net,作者:CodeAllen的博客,版权归原作者所有,如需转载,请联系作者。

原文链接:allen5g.blog.csdn.net/article/details/116861329

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。