#include <stdio.h>
#include <stdlib.h>
#include <malloc.h> #define MAXVEX 30 //最大顶点数
#define MAXEDGE 30 //最大边数
#define INFINITY 65535 //∞ //定义全局变量
int *etv, *ltv;//事情最早发生和最迟发生指针数组
int *stack2;//用于存储拓扑排序的栈
int top2;//用于指向stack2栈指针 /* 邻接矩阵结构 */
typedef struct
{
int vexs[MAXVEX];//顶点下标
int arc[MAXVEX][MAXVEX];//矩阵(路径)
int numVertexes, numEdges;//当前图中的顶点数和边数
}MGraph; /* 邻接表结构 */
typedef struct EdgeNode //
{//边表结点
int adjvex;//顶点下标
int weight;//路径
struct EdgeNode *next;//指向想一个边表结点
}EdgeNode; typedef struct VertexNode
{//顶点结点
int in;//入度
int data;//顶点信息
EdgeNode *firstedge;//指向边表头指针
}VertexNode, AdjList[MAXVEX]; typedef struct
{
AdjList adjList;//顶点向量
int numVertexes, numEdges;//顶点数和边数
}graphAdjList, *GraphAdjList; void CreateMGraph(MGraph *G)
{/* 构建图 */
int i, j; // printf("请输入顶点数和边数:\n");
G->numVertexes = ;
G->numEdges = ; //初始化顶点下标
for(i=; i<G->numVertexes; i++)
G->vexs[i] = i; //初始化矩阵
for(i=; i<G->numVertexes; i++)
for(j=; j<G->numVertexes; j++)
if(i == j)
G->arc[i][j] = ;
else
G->arc[i][j] = INFINITY; //内置输入
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ;
G->arc[][] = ; return ;
} void CreateALGraph(MGraph G, GraphAdjList *GL)
{/* 利用邻接矩阵,构建邻接表 */
int i, j;
EdgeNode *e; *GL = (GraphAdjList)malloc(sizeof(graphAdjList));//*GL代表主函数的GL指向
(*GL)->numVertexes = G.numVertexes;/* 读取信息 */
(*GL)->numEdges = G.numEdges; //初始化
for(i=; i<G.numVertexes; i++)
{
(*GL)->adjList[i].in = ;
(*GL)->adjList[i].data = G.vexs[i];//读取顶点下标
(*GL)->adjList[i].firstedge = NULL;
} //构建邻接表
for(i=; i<G.numVertexes; i++)
for(j=; j<G.numVertexes; j++)
if( != G.arc[i][j] && INFINITY > G.arc[i][j])
{//若存在路径
e = (EdgeNode *)malloc(sizeof(EdgeNode));//申请
e->adjvex = j;//存顶点
e->weight = G.arc[i][j];//存路径
e->next = (*GL)->adjList[i].firstedge;//存表头指针
(*GL)->adjList[i].firstedge = e;//头插
(*GL)->adjList[j].in ++;//顶点入度+1
}
return ;
} void TopologicalSort(GraphAdjList GL)
{/* 拓扑排序 */
EdgeNode *e;
int i, gettop, k;
int top = ;//用于指向stack栈顶
int count = ;//技术输出
int *stack;//建栈存储入度位0的顶点
stack = (int *)malloc(sizeof(int));
for(i=; i<GL->numVertexes; i++)//把所有入度位0的顶点如stack栈中
if( == GL->adjList[i].in)
stack[++top] = i; etv = (int *)malloc(sizeof(int) * GL->numVertexes);//最早发生etv指针申请空间
for(i=; i<GL->numVertexes; i++)//初始化最早发生etv数组
etv[i] = ; stack2 = (int *)malloc(sizeof(int) * GL->numVertexes);//存储拓扑排序序列
top2 = ;//用于指向stack2栈顶
printf("Topological:\t");
while( != top)
{//若有顶点入度为0
gettop = stack[top--];//出栈
printf("%3d->", GL->adjList[gettop].data);//输出出栈的栈顶的顶点信息
count ++;//输出记数 stack2[++top2] = gettop;//出栈元素赋给存储拓扑序列栈 for(e=GL->adjList[gettop].firstedge; e; e=e->next)
{//出栈的栈顶元素若有邻接点
k = e->adjvex;//邻接点-顶点下标
if(! (--GL->adjList[k].in))//邻接点顶点下标-1(gettop已指向),是否入度位0?
stack[++top] = k;//是则入stack的栈 /*出栈的最早发生时间值+出栈邻接表的路径 > 出栈邻接表顶点下标的最早发生时间值
就是v0-v1-v3和v0-v2-v3都是从起点到达汇点,3哪一个路径较远 */
if((etv[gettop] + e->weight) > etv[k])
etv[k] = etv[gettop] + e->weight;
}
}
printf("\n"); if(count < GL->numVertexes)//若有环,则结束程序
exit(-); return ;
} void CriticalPath(GraphAdjList GL)
{/* 关键路径 */
EdgeNode *e;
int i, gettop, k, j;
int ete, lte;//最早发生和最迟发生的变量 TopologicalSort(GL);//调用拓扑排序函数 ltv = (int *)malloc(sizeof(int) * GL->numVertexes);//最迟发生指针边表指向申请空间
for(i=; i<GL->numVertexes; i++)//初始化最迟发生数组
ltv[i] = etv[GL->numVertexes - ];//起到汇最大值 //输出最早发生数组
printf("etv:\t\t");
for(i=; i<GL->numVertexes; i++)
printf("%3d->", etv[i]);
printf("\n"); while( != top2)
{//存放拓扑排序数列
gettop = stack2[top2--];
for(e=GL->adjList[gettop].firstedge; e; e=e->next)
{
k = e->adjvex;
if((ltv[k] - e->weight) < ltv[gettop])
ltv[gettop] = ltv[k] - e->weight;
/*最晚发生时间值(出stack2(存拓扑排序)栈元素的邻接点顶点下标) - 邻接路径 < 最晚发生数组【出栈元素0】
用拓扑排序的最长路径 - 邻接路径 < 最晚发生值[出栈元素]*/
}
} printf("ltv:\t\t");//输出最晚值数组
for(i=; i<GL->numVertexes; i++)
printf("%3d->", ltv[i]);
printf("\n"); for(j=; 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)//相等即在关键路径上
printf("<v%d - v%d> length : %d \n", GL->adjList[j].data, GL->adjList[k].data, e->weight);
} return ;
} int main(void) {
MGraph G;
GraphAdjList GL;
system("title 关键路径");
CreateMGraph(&G);
CreateALGraph(G, &GL);
CriticalPath(GL); return ;
}

关键路径(CriticalPath)算法的更多相关文章

  1. 关键路径——CriticalPath算法

    背景:本文是在小甲鱼数据结构教学视频中的代码的基础上,添加详细注释而完成的.该段代码并不完整,仅摘录了核心算法部分,结合自己的思考,谈谈理解. 关键路径: 即决定一项工程的完成时间的路径. 如下图所示 ...

  2. 算法与数据结构(八) AOV网的关键路径

    上篇博客我们介绍了AOV网的拓扑序列,请参考<数据结构(七) AOV网的拓扑排序(Swift面向对象版)>.拓扑序列中包括项目的每个结点,沿着拓扑序列将项目进行下去是肯定可以将项目完成的, ...

  3. 算法与数据结构(八) AOV网的关键路径(Swift版)

    上篇博客我们介绍了AOV网的拓扑序列,请参考<数据结构(七) AOV网的拓扑排序(Swift面向对象版)>.拓扑序列中包括项目的每个结点,沿着拓扑序列将项目进行下去是肯定可以将项目完成的, ...

  4. 图->有向无环图->求关键路径

    文字描述 与AOV-网相对应的是AOE-网(Activity on Edge)即边表示活动的网.AOE-网是一个带权的有向无环图.其中,顶点表示事件Event,弧表示活动,权表示活动持续的时间.通常, ...

  5. AOE网与关键路径简介

    前面我们说过的拓扑排序主要是为解决一个工程能否顺序进行的问题,但有时我们还需要解决工程完成需要的最短时间问题.如果我们要对一个流程图获得最短时间,就必须要分析它们的拓扑关系,并且找到当中最关键的流程, ...

  6. java数据结构_笔记(5)_图的算法

    图的算法 1 图的遍历图的遍历就是从图中某个顶点出发,按某种方法对图中所有顶点访问且仅访问一次.遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础. 2 深度优先遍历从图中某个顶点V 出发 ...

  7. MindFusion 中节点关键路径的遍历

    工作中总能遇到 一些 奇葩的需求,提出这些奇葩需求的人,多半也是奇葩的人,要么不懂相关的计算机软件知识,要么就是瞎扯蛋,异想天开,然而这些奇葩的需求,我也总能碰到.言规正传,在一次项目中,使用了 Mi ...

  8. 数据结构(c语言版)代码

    第1章  绪论       文档中源码及测试数据存放目录:数据结构\▲课本算法实现\▲01 绪论  概述        第一章作为绪论,主要介绍了数据结构与算法中的一些基本概念和术语.对于这些概念术语 ...

  9. 返回数据方法DeaCacheCommand,由CRL自动实现

    越来越多的人学起了前端,或许部分的初衷仅是它简单易上手以及好找工作,毕竟几年前只会个html和css就能有工作,悄悄告诉泥萌,这也是博主一年前的初衷 还好numpy, scikit-learn都提供了 ...

随机推荐

  1. C语言的本质(32)——C语言与汇编之C语言内联汇编

    用C写程序比直接用汇编写程序更简洁,可读性更好,但效率可能不如汇编程序,因为C程序毕竟要经由编译器生成汇编代码,尽管现代编译器的优化已经做得很好了,但还是不如手写的汇编代码.另外,有些平台相关的指令必 ...

  2. 2.x ESL第二章习题 2.8

    题目 代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 3 ...

  3. Python-memcached的基本使用 - Flynewton成长点滴 - 开源中国社区

    Python-memcached的基本使用 - Flynewton成长点滴 - 开源中国社区 Python-memcached的基本使用 发表于3年前(2010-12-04 00:02)   阅读(9 ...

  4. 【转】android电池(四):电池 电量计(MAX17040)驱动分析篇

    关键词:android 电池  电量计  MAX17040 任务初始化宏 power_supply 平台信息:内核:linux2.6/linux3.0系统:android/android4.0 平台: ...

  5. 设置MySQL数据表主键

    设置MySQL数据表主键: 使用“primary key”关键字创建主键数据列.被设置为主键列不允许出现重复的值,很多情况下与“auto_increment”递增数字相结合.如下SQL语句所示: My ...

  6. java-随学随记之基础篇

    一.Java是一门高级语言,具有跨平台性(一次编译到处运行) 1.javac.exe命令,编译器   javac 源文件名.java 2.java.exe命令,启动虚拟机 java 类名 二.环境变量 ...

  7. JQ each

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. 关于Oracle中查询结果为未选定行

    今天在做关于Oracle查询语句的练习时,碰到这么一个题目:找出EMP表中姓名(ENAME)第三个字母是A的员工姓名.我的Scott.emp表的现有数据如下: SQL> select * fro ...

  9. IOS创建单例的两种方法

    1.0  苹果官方写法:  static AccountManager *DefaultManager = nil; + (AccountManager *)defaultManager { if ( ...

  10. 实现一个宽和高都是100像素的div可以用鼠标拖拽移动的效果

    html,body{ width:100%;height:100%;margin:0px;padding:0px; } #box{ width:100px;height:100px;backgroun ...