当前位置: 首页 > news >正文

数据结构 -- 图的应用(二)

图的应用

有向无环图(DAG)

有向无环图:若一个有向图中不存在环,则称为有向无环图,简称DAG图

DAG描述表达式

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

方法:

利用规律:最终有向无环图中,定点中不会出现重复的操作数

step1:把各个操作数不重复地排成一排

step2:标出各个运算符生效的顺序(先后顺序有点出入无所谓)

step3:按顺序加入运算符,注意分层

step4:自底向上逐层检查同层地运算符是否合体

使用有向无环图描述表达式结果不唯一
在这里插入图片描述

AOV网

AOV网用定点表示活动的网

用DAG图(有向无环图)表示一个工程。顶点表示活动,有向边<vi,vj>表示活动vi必须先于活动vj进行

在这里插入图片描述

拓扑排序

找到要做事的先后顺序

实现:

① 从AOV网中选择一个没有前驱(入度为0)的顶点并输出

② 从网中删除该顶点和所有以它为起点的有向边

③ 重复①和②直到当前的AOV为空或当前网中不存在无前驱的顶点为止(说明存在回路)

#define MaxVertexNum 100
typedef struct AcrNode{  //边表结点int adjvex;struct ArcNode *nextarc;		//指向下一条弧的指针//InfoType info		//网的边权值
}ArcNode;
typedef struct VNode{	//顶点表结点VertexType data;	//顶点信息ArcNode *firstarc;		//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];
typedef struct{AdjList wertices;	//邻接表int vexnum,arcnum;	//图的顶点数和弧数}Graph;
bool TopologicalSrot(Graph G){initStack(S);for(int i = 0;i<G.vexnum;i++){if(indegree[i] == 0)Push(s,i);		//将所有入度为0的顶点进栈}int count = 0;		//计数,记录当前已经输出的顶点数while(!isEmpty(S)){		//栈不空,则存在入度为0的顶点Pop(S,i);			//栈顶元素出栈print[count++]=i;		//输出顶点ifor(p=G.vertices[i].firstarc;p;p=p->nextarc){//将所有i指向的顶点的入度减1,并且将入度减为0的顶点压入栈s中v = p->adjvex;if(!(--indegree[v]))Push(S,v);		//入度为0,则入栈}}//whileif(count<G.vexnum)return false;		//排序失败,说明有向图中有回路elsereturn true;		//拓扑排序成功
}
逆拓扑排序

对于一个AOV网,如果采用下列步骤进行排序,则称之为逆拓扑排序:

① 从AOV网中选择一个没有后继(出度为0)的顶点并输出

② 从网中删除该顶点和所有以它为起点的有向边

③ 重复①和②直到当前的AOV为空

【思考】使用不同的存储结构对时间复杂度的影响

如果使用邻接表进行存储,要对所有边进行遍历才能找到顶点的出度,时间复杂度高(低效)

邻接矩阵更方便些

【补充】

逆邻接表:每个顶点连接的顶点是指向当前顶点的顶点

逆拓扑排序的实现(DFS算法)
void DFSTraverse(Graph G){		//对图G进行深度优先遍历for(v = 0;v<G.vexnum;++v)visited[v] = FALSE;		//初始化已访问标记数据for(v = 0;v<G.vexnum;++v)	//本代码中是从v=0开始遍历if(!visited[v])DFS(G.v);
}
void DFS(Graph G,int v){		//从顶点v出发,深度优先遍历图Gvisit(v);					//访问顶点vvisited[v] = TRUE;			//设已访问标记for(w = FirstNeighbor(G,v);w>=0;w = NextNeighbor(G,v,w))if(!visited[w]){		//w为u的尚未访问的邻接顶点DFS(G,w);}	//if
}

DFS实现逆拓扑排序:在顶点退栈前输出

AOE网

在带权有向图中,以顶点表示事件,以有点改变表示活动,以边上的权值表示完成该活动的开销(如完成活动所需的时间),称之为用边表示活动的网络,简称AOE网

在这里插入图片描述

性质:

① 只有在某顶点所代表的事件发生后,从该顶点出发阿德各有向边所代表的活动才能开始

② 只有在进入某顶点的各有向边所代表的活动都已结束时,该顶点所代表的事件才能发生

另外,有些活动是可以并发进行的

关键路径

在AOE网中仅有一个入度为0的顶点,称为开始顶点(源点),在所有路径中,具有最大路径长度称为关键路径,而把关键路径上的活动称为关键活动

完成整个工程的最短时间就是关键路径的长度,若关键活动不能按时完成,则整个工程的完成时间就会延长

在这里插入图片描述

事件vk的最早发生时间ve(k) – 决定了所有从vk开始的活动能够开工的最早时间

活动ai最早开始时间e(i)) – 指该活动弧的起点所表示的事件的最早发生时间

事件vk的最是发生时间vl(k) – 指在不推迟整个过程完成的前提下,该时间最迟必须发生时间

活动ai的最迟开始时间l(i) – 指该活动弧的重点所表示事件的最迟发生时间与该活动所需时间之差

在这里插入图片描述

时间余量为零的活动为关键活动

由关键活动组成的路径就是关键路径

求关键路径的步骤

① 求各个事件的最早发生时间

按照拓扑排序序列,依次求各个顶点的ve(k)

② 求所有事件的最迟发生时间

按逆拓扑排序,依次求各个顶点的vl(k)

③ 求所有活动的最早发生时间

④求所有活动的最迟发生时间

⑤ 求所有活动的时间余量

关键活动、关键路径的特性

若关键活动耗时增加,则整个工程的工期将增长

缩短关键活动的时间,可以缩短整个工程的工期

当缩短到一定程度,关键路径可能会变成非关键活动

http://www.xdnf.cn/news/189649.html

相关文章:

  • 机器学习中的数据转换:关键步骤与最佳实践
  • 多模态革命!拆解夸克AI相机技术架构:如何用视觉搜索重构信息交互?(附开源方案对比)
  • 讯飞星辰焕新发布!Agent规模化应用的通关密码
  • 【“星瑞” O6 评测】 — CPU llama.cpp不同优化速度对比
  • 【Shell 脚本入门】轻松上手的实战指南
  • 深度学习: AI 体育领域
  • 成员方法的详细说明(结合Oracle官方文档)
  • 12分区 3号机 送风分区送风 会远程启,不会远停
  • 搭建dns的正向解析
  • QGIS+mcp的安装和使用
  • DeepSeek智能时空数据分析(六):大模型NL2SQL绘制城市之间连线
  • 云原生开发革命:iVX 如何实现 “资源即插即用” 的弹性架构?
  • 《Masked Autoencoders Are Scalable Vision Learners》---CV版的BERT
  • 微信小程序开发中关于首屏加载、本地数据持久化的思考
  • 旋转位置编码RoPE
  • TypeScript中的函数类型定义与类型约束
  • 有哪些和PPT自动生成有关的MCP项目?
  • 详解RabbitMQ工作模式之简单模式
  • Vue 对话框出现时,为什么滚动鼠标还是能滚动底层元素
  • Docker 常用命令(涵盖多个方面)
  • 数据结构第七章(一)-顺序查找和折半查找
  • CMCC RAX3000M使用Tftpd刷写OpenWrt固件的救砖方法
  • Python实现SSE流式推送
  • AutoGen 框架深度解析:构建多智能体协作的事件驱动架构
  • SQL 易混易错知识点笔记1(drop,role,%,localhost)
  • Flinkcdc 实现 MySQL 写入 Doris
  • 导入使用 Blender 创建的 glTF/glb 格式的 3D 模型
  • 从千兆到40G:飞速(FS)助力制造企业构建高可靠智能生产网络
  • Ocelot的应用案例
  • 整合性安全总结(ISS)早期规划