_DataStructure_C_Impl:AOE网的关键路径
//_DataStructure_C_Impl:CriticalPath
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"SeqStack.h"
//图的邻接表类型定义
typedef char VertexType[4];
typedef int InfoPtr; //定义为整型,为了存放权值
typedef int VRType; #define MaxSize 50 //最大顶点个数
typedef enum{DG,DN,UG,UN}GraphKind; //图的类型:有向图、有向网、无向图和无向网
//边结点的类型定义
typedef struct ArcNode{
int adjvex; //邻接点域,弧指向的顶点的位置
InfoPtr *info; //弧的权值
struct ArcNode *nextarc; //指示下一个与该顶点相邻接的顶点
}ArcNode;
//头结点的类型定义
typedef struct VNode{
VertexType data; //用于存储顶点
ArcNode *firstarc; //指示第一个与该顶点邻接的顶点
}VNode,AdjList[MaxSize];
//图的类型定义
typedef struct{
AdjList vertex;
int vexnum,arcnum; //图的顶点数目与弧的数目
GraphKind kind; //图的类型
}AdjGraph;
//返回图中顶点相应的位置
int LocateVertex(AdjGraph G,VertexType v){
int i;
for(i=0;i<G.vexnum;i++)
if(strcmp(G.vertex[i].data,v)==0)
return i;
return -1;
}
//採用邻接表存储结构,创建有向网N
void CreateGraph(AdjGraph *N){
int i,j,k,w;
VertexType v1,v2; //定义两个顶点v1和v2
ArcNode *p;
printf("请输入图的顶点数,边数(逗号分隔): ");
scanf("%d,%d",&(*N).vexnum,&(*N).arcnum);
printf("请输入%d个顶点的值:\n",N->vexnum);
for(i=0;i<N->vexnum;i++){
scanf("%s",N->vertex[i].data);
N->vertex[i].firstarc=NULL; //将相关联的顶点置为空
}
printf("请输入弧尾和弧头(以空格作为间隔):\n");
for(k=0;k<N->arcnum;k++){ //建立边链表
scanf("%s%s%*c%d",v1,v2,&w);
i=LocateVertex(*N,v1);
j=LocateVertex(*N,v2);
//j为弧头i为弧尾创建邻接表
p=(ArcNode *)malloc(sizeof(ArcNode));
p->adjvex=j;
p->info=(InfoPtr*)malloc(sizeof(InfoPtr));
*(p->info)=w;
//将p指向的结点插入到边表中
p->nextarc=N->vertex[i].firstarc;
N->vertex[i].firstarc=p;
}
(*N).kind=DN;
}
//销毁无向图G
void DestroyGraph(AdjGraph *G){
int i;
ArcNode *p,*q;
for(i=0;i<(*G).vexnum;++i){ //释放图中的边表结点
p=G->vertex[i].firstarc; //p指向边表的第一个结点
if(p!=NULL){ //假设边表不为空,则释放边表的结点
q=p->nextarc;
free(p);
p=q;
}
}
(*G).vexnum=0; //将顶点数置为0
(*G).arcnum=0; //将边的数目置为0
}
//输出图的邻接表
void DisplayGraph(AdjGraph G){
int i;
ArcNode *p;
printf("%d个顶点:\n",G.vexnum);
for(i=0;i<G.vexnum;i++)
printf("%s ",G.vertex[i].data);
printf("\n%d条边:\n",G.arcnum);
for(i=0;i<G.vexnum;i++)
{
p=G.vertex[i].firstarc;
while(p)
{
printf("<%s,%s,%d> ",G.vertex[i].data,G.vertex[p->adjvex].data,*(p->info));
p=p->nextarc;
}
printf("\n");
}
}
//*********************************************************
int ve[MaxSize]; //ve存放事件最早发生时间
/*採用邻接表存储结构的有向网N的拓扑排序,并求各顶点相应事件的最早发生时间ve*/
/*假设N无回路。则用用栈T返回N的一个拓扑序列,并返回1,否则为0*/
int TopologicalOrder(AdjGraph N,SeqStack *T){
int i,k,count=0;
int indegree[MaxSize]; //数组indegree存储各顶点的入度
SeqStack S;
ArcNode *p;
//将图中各顶点的入度保存在数组indegree中
for(i=0;i<N.vexnum;i++) //将数组indegree赋初值
indegree[i]=0;
for(i=0;i<N.vexnum;i++){
p=N.vertex[i].firstarc;
while(p!=NULL){
k=p->adjvex;
indegree[k]++;
p=p->nextarc;
}
}
//初始化栈S
InitStack(&S);
printf("拓扑序列:");
for(i=0;i<N.vexnum;i++)
if(!indegree[i]) //将入度为零的顶点入栈
PushStack(&S,i);
InitStack(T); //初始化逆拓扑排序顶点栈
for(i=0;i<N.vexnum;i++) //初始化ve
ve[i]=0;
while(!StackEmpty(S)){ //假设栈S不为空
PopStack(&S,&i); //从栈S将已拓扑排序的顶点i弹出
printf("%s ",N.vertex[i].data);
PushStack(T,i); //i号顶点入逆拓扑排序栈T
count++; //对入栈T的顶点计数
for(p=N.vertex[i].firstarc;p;p=p->nextarc){ //处理编号为i的顶点的每一个邻接点
k=p->adjvex; //顶点序号为k
if(--indegree[k]==0) //假设k的入度减1后变为0,则将k入栈S
PushStack(&S,k);
if(ve[i]+*(p->info)>ve[k]) //计算顶点k相应的事件的最早发生时间
ve[k]=ve[i]+*(p->info);
}
}
if(count<N.vexnum){
printf("该有向网有回路\n");
return 0;
}else
return 1;
}
//输出AOE网N的关键路径
int CriticalPath(AdjGraph N){
int vl[MaxSize]; //事件最晚发生时间
SeqStack T;
int i,j,k,e,l,dut,value,count,e1[MaxSize],e2[MaxSize];
ArcNode *p;
if(!TopologicalOrder(N,&T)) //假设有环存在,则返回0
return 0;
value=ve[0];
for(i=1;i<N.vexnum;i++)
if(ve[i]>value)
value=ve[i]; //value为事件的最早发生时间的最大值
for(i=0;i<N.vexnum;i++) //将顶点事件的最晚发生时间初始化
vl[i]=value;
while(!StackEmpty(T)) //按逆拓扑排序求各顶点的vl值
for(PopStack(&T,&j),p=N.vertex[j].firstarc;p;p=p->nextarc){ //弹出栈T的元素,赋给j,p指向j的后继事件k
k=p->adjvex;
dut=*(p->info); //dut为弧<j,k>的权值
if(vl[k]-dut<vl[j])//计算事件j的最迟发生时间
vl[j]=vl[k]-dut;
}
printf("\n事件的最早发生时间和最晚发生时间\ni ve[i] vl[i]\n");
for(i=0;i<N.vexnum;i++) //输出顶点相应的事件的最早发生时间最晚发生时间
printf("%d %d %d\n",i,ve[i],vl[i]);
printf("关键路径为:(");
for(i=0;i<N.vexnum;i++) //输出关键路径经过的顶点
if(ve[i]==vl[i])
printf("%s ",N.vertex[i].data);
printf(")\n");
count=0;
printf("活动最早開始时间和最晚開始时间\n 弧 e l l-e\n");
for(j=0;j<N.vexnum;j++)
for(p=N.vertex[j].firstarc;p;p=p->nextarc){
k=p->adjvex;
dut=*(p->info); //dut为弧<j,k>的权值
e=ve[j]; //e就是活动<j,k>的最早開始时间
l=vl[k]-dut; //l就是活动<j,k>的最晚開始时间
printf("%s→%s %3d %3d %3d\n",N.vertex[j].data,N.vertex[k].data,e,l,l-e);
if(e==l){ //将关键活动保存在数组中
e1[count]=j;
e2[count]=k;
count++;
}
}
printf("关键活动为:");
for(k=0;k<count;k++) //输出关键路径
{
i=e1[k];
j=e2[k];
printf("(%s→%s) ",N.vertex[i].data,N.vertex[j].data);
}
printf("\n");
return 1;
}
void main(){
AdjGraph N;
CreateGraph(&N); /*採用邻接表存储结构创建有向网N*/
DisplayGraph(N); /*输出有向网N*/
CriticalPath(N); /*求网N的关键路径*/
DestroyGraph(&N); /*销毁网N*/
system("pause");
}
#pragma once
#include<stdio.h>
#include<stdlib.h>
#define StackSize 100
typedef int DataType; //栈元素类型定义
typedef struct{
DataType stack[StackSize];
int top;
}SeqStack;
//将栈初始化为空栈仅仅须要把栈顶指针top置为
void InitStack(SeqStack *S){
S->top=0;//把栈顶指针置为0
}
//推断栈是否为空。栈为空返回1,否则返回0
int StackEmpty(SeqStack S){
if(S.top==0)
return 1;
else
return 0;
}
//取栈顶元素。将栈顶元素值返回给e,并返回1表示成功;否则返回0表示失败。
int GetTop(SeqStack S,DataType *e){
if(S.top<=0){ //在取栈顶元素之前。推断栈是否为空
printf("栈已经空!\n");
return 0;
}else{
*e=S.stack[S.top-1]; //在取栈顶元素
return 1;
}
}
//将元素e进栈。元素进栈成功返回1,否则返回0
int PushStack(SeqStack *S,DataType e){
if(S->top>=StackSize){ //在元素进栈前,推断是否栈已经满
printf("栈已满。不能进栈! \n");
return 0;
}else{
S->stack[S->top]=e; //元素e进栈
S->top++; //改动栈顶指针
return 1;
}
}
//出栈操作。将栈顶元素出栈。并将其赋值给e。出栈成功返回1。否则返回0
int PopStack(SeqStack *S,DataType *e){
if(S->top<=0){ //元素出栈之前,推断栈是否为空
printf("栈已经没有元素,不能出栈!\n");
return 0;
}else{
S->top--; //先改动栈顶指针。即出栈
*e=S->stack[S->top]; //将出栈元素赋值给e
return 1;
}
}
//求栈的长度。即栈中元素个数,栈顶指针的值就等于栈中元素的个数
int StackLength(SeqStack S){
return S.top;
}
//清空栈的操作
void ClearStack(SeqStack *S){
S->top=0;
}
_DataStructure_C_Impl:AOE网的关键路径的更多相关文章
- AOE网与关键路径简介
		
前面我们说过的拓扑排序主要是为解决一个工程能否顺序进行的问题,但有时我们还需要解决工程完成需要的最短时间问题.如果我们要对一个流程图获得最短时间,就必须要分析它们的拓扑关系,并且找到当中最关键的流程, ...
 - 基于AOE网的关键路径的求解
		
[1]关键路径 在我的经验意识深处,“关键”二字一般都是指临界点. 凡事万物都遵循一个度的问题,那么存在度就会自然有临界点. 关键路径也正是研究这个临界点的问题. 在学习关键路径前,先了解一个AOV网 ...
 - AOE网与关键路径
		
声明:图片及内容基于https://www.bilibili.com/video/BV1BZ4y1T7Yx?from=articleDetail 原理 AOE网 关键路径 数据结构 核心代码 Topo ...
 - AOE网的关键路径的计算
		
求关键路径,只需理解顶点(事件)和边(活动)各自的两个特征属性以及求法即可: Ø 先根据首结点的Ve(j)=0由前向后(正拓扑序列)计算各顶点的最早发生时间 Ø 再根据终结点的Vl(j)等于它的V ...
 - 教你轻松计算AOE网关键路径(转)
		
原文链接:http://blog.csdn.net/wang379275614/article/details/13990163 本次结合系统分析师-运筹方法-网络规划技术-关键路径章节,对原文链接描 ...
 - 教你轻松计算AOE网关键路径
		
认识AOE网 有向图中,用顶点表示活动,用有向边表示活动之间开始的先后顺序,则称这种有向图为AOV网络:AOV网络可以反应任务完成的先后顺序(拓扑排序). 在AOV网的边上加上权值表示完成该活动所需的 ...
 - SDUT 2498 AOE网上的关键路径
		
AOE网上的关键路径 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 一个无环的有向图称为无 ...
 - 数据结构关于AOV与AOE网的区别
		
AOV网,顶点表示活动,弧表示活动间的优先关系的有向图. 即如果a->b,那么a是b的先决条件. AOE网,边表示活动,是一个带权的有向无环图, 其中顶点表示事件,弧表示活动,权表示活动持续时间 ...
 - AOV图与拓扑排序&AOE图与关键路径
		
AOV网:所有的工程或者某种流程可以分为若干个小的工程或阶段,这些小的工程或阶段就称为活动.若以图中的顶点来表示活动,有向边表示活动之间的优先关系,则这样活动在顶点上的有向图称为AOV网. 拓扑排序算 ...
 
随机推荐
- python的模块导入
			
单个文件导入:导入的模块可以是一个py文件(放置在当前文件的同级目录.默认路径等) 导入:import 模块名 使用:模块名.函数名 导入:from 模块名 import * 使用:函数名 ----- ...
 - SwiftUI 官方教程(四)
			
SwiftUI 官方教程(四) 4. 自定义 Image View 搞定名称和位置 view 后,我们来给地标添加图片. 这不需要添加很多代码,只需要创建一个自定义 view,然后给图片加上遮罩.边框 ...
 - ORACLE 11g 生产中高水位线(HWM)处理
			
数据库中表不断的insert,delete,update,导致表和索引出现碎片.这会导致HWM之前有很多的空闲空间,而oracle在做全表扫描的时候会读取HWM一下的所有块,这样会产生更多的IO,影响 ...
 - INFORMIX MATCHES的使用详解
			
MATCHES 运算符返回 TRUE ,如果一个字符串与给定的掩码匹配. 语法 expr [NOT] MATCHES mask [ ESCAPE "char" ] ex ...
 - Charles设置抓取https请求
			
1.在手机上设置HTTP代理,将手机与电脑连接. 打开手机设置-WLAN,设置代理 2.(iPhone)使用iPhone自带的浏览器打开Safari,并输入地址:http://charlesproxy ...
 - Android Toolbar使用及Fragment中的Toolbar处理
			
Toolbar作为ActionBar使用介绍 本文介绍了在Android中将Toolbar作为ActionBar使用的方法.并且介绍了在Fragment和嵌套Fragment中使用Toolbar作为A ...
 - hdu1385 Minimum Transport Cost   字典序最小的最短路径  Floyd
			
求最短路的算法最有名的是Dijkstra.所以一般拿到题目第一反应就是使用Dijkstra算法.但是此题要求的好几对起点和终点的最短路径.所以用Floyd是最好的选择.因为其他三种最短路的算法都是单源 ...
 - 最小环 hdu1599  poj1734
			
最小环用floyd改编. hdu1599特殊一些.要求至少有三个不同的点,并且除了起点与终点重合外,中间不能有环.有点很奇怪,最大值不能为0x3f3f3f3f. poj1374就没那么讲究. //hd ...
 - bootstrap modal 一闪
			
原因可能是因为bootstrap.min.js(bootstrap.js) 和modal.js重复引用导致的,而且重复引用还会引致bootstrap的js事件失效.
 - 从无到有创建一个grunt项目
			
在安装好grunt的前提下创建一个grunt的项目: 1.首先创建一个项目文件 就叫grunt-project 2.进入这个文件 创建一个index.html 在创建一个js文件,进去创建一个inde ...