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

有向无环图(Directed Acyclic Graph, DAG)介绍(环检测、DFS法、Kahn算法、)

https://www.bilibili.com/video/BV1mY4y1V7kH

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

文章目录

  • 有向无环图(DAG)介绍
    • 1. **边的方向性**:每条边都有明确的方向(如从顶点 A→BA \rightarrow BAB,与 B→AB \rightarrow ABA 不同)。
    • 2. **无环性**:图中不存在任何形式的环路,即无法从某个顶点出发,沿着边最终回到起点。
    • **关键特性**
      • 1. **拓扑排序可行性**
      • 2. **入度与出度**
      • 3. **子结构共享**
    • **应用场景**
      • 1. **任务调度与依赖管理**
        • - **课程安排**:根据课程的先修要求,确定选课顺序(如线性代数需在微积分之前学习)。
        • - **编译器优化**:通过 DAG 共享公共子表达式,减少重复计算(如表达式 `((a+b)*(c+d))` 的优化)。
        • - **项目管理**:安排任务的执行顺序(如软件开发中的模块依赖)。
      • 2. **数据流处理**
        • - **Apache Airflow**:工作流调度工具,通过 DAG 表示任务之间的依赖关系。
        • - **区块链技术**:IOTA 的 Tangle 技术利用 DAG 结构提升交易处理效率(与传统区块链的链式结构不同)。
      • 3. **版本控制系统**
        • - **Git**:提交历史的合并结构(如分支和合并操作)形成 DAG,而非线性链表。
      • 4. **最短/最长路径问题**
    • **DAG 的算法与操作**
      • 1. **环检测**
        • - **DFS 法**:深度优先搜索时维护递归栈,若遇到已访问且仍在栈中的节点,则存在环。
        • - **Kahn 算法**:通过入度统计和队列处理判断是否存在环(拓扑排序的变种)。
      • 2. **拓扑排序**
        • - **Kahn 算法**:
        • - **DFS 后序逆序**:对 DAG 进行 DFS,按完成时间逆序排列得到拓扑序列。
      • 3. **最长/最短路径计算**
        • - **动态规划法**:按拓扑顺序处理顶点,更新邻接顶点的路径值(适用于带权 DAG)。
    • **DAG 与树的区别**
    • **代码示例:Kahn 算法(JavaScript 实现)**
    • **总结**

有向无环图(DAG)介绍

有向无环图(Directed Acyclic Graph, DAG) 是一种特殊的有向图,其核心特点是:

1. 边的方向性:每条边都有明确的方向(如从顶点 A→BA \rightarrow BAB,与 B→AB \rightarrow ABA 不同)。

2. 无环性:图中不存在任何形式的环路,即无法从某个顶点出发,沿着边最终回到起点。


关键特性

1. 拓扑排序可行性

  • DAG 必然存在至少一个拓扑排序,即所有顶点可以排成一个线性序列,使得每条边的起点在终点之前。
  • 拓扑排序是 DAG 的核心性质,常用于任务调度、依赖管理等问题。

2. 入度与出度

  • 每个 DAG 中必然存在至少一个入度为 0 的顶点(无前置依赖),以及至少一个出度为 0 的顶点(无后续依赖)。

3. 子结构共享

  • DAG 可以高效表示具有公共子结构的表达式(如编译原理中的基本块优化)。

应用场景

1. 任务调度与依赖管理

- 课程安排:根据课程的先修要求,确定选课顺序(如线性代数需在微积分之前学习)。
- 编译器优化:通过 DAG 共享公共子表达式,减少重复计算(如表达式 ((a+b)*(c+d)) 的优化)。
- 项目管理:安排任务的执行顺序(如软件开发中的模块依赖)。

2. 数据流处理

- Apache Airflow:工作流调度工具,通过 DAG 表示任务之间的依赖关系。
- 区块链技术:IOTA 的 Tangle 技术利用 DAG 结构提升交易处理效率(与传统区块链的链式结构不同)。

3. 版本控制系统

- Git:提交历史的合并结构(如分支和合并操作)形成 DAG,而非线性链表。

4. 最短/最长路径问题

- DAG 上的最短路径和最长路径(关键路径)可以通过拓扑排序在 O(V+E)O(V + E)O(V+E) 时间内高效求解。

DAG 的算法与操作

1. 环检测

- DFS 法:深度优先搜索时维护递归栈,若遇到已访问且仍在栈中的节点,则存在环。
- Kahn 算法:通过入度统计和队列处理判断是否存在环(拓扑排序的变种)。

2. 拓扑排序

- Kahn 算法
  1. 统计每个顶点的入度。
  2. 将入度为 0 的顶点加入队列。
  3. 依次处理队列中的顶点,减少其邻居的入度,若邻居入度为 0 则入队。
  4. 若最终处理顶点数不等于总顶点数,则图中存在环。
- DFS 后序逆序:对 DAG 进行 DFS,按完成时间逆序排列得到拓扑序列。

3. 最长/最短路径计算

- 动态规划法:按拓扑顺序处理顶点,更新邻接顶点的路径值(适用于带权 DAG)。

DAG 与树的区别

特性树(Tree)DAG(有向无环图)
方向性无向或有向(如二叉树)有向
环路无环无环
父节点数每个节点至多一个父节点节点可有多个父节点
连通性连通可连通或非连通

代码示例:Kahn 算法(JavaScript 实现)

function kahnTopologicalSort(graph) {const inDegree = {}; // 记录每个节点的入度const queue = [];    // 存储入度为 0 的节点const result = [];   // 存储拓扑排序结果// 初始化入度表for (const node in graph) {inDegree[node] = 0;}// 计算每个节点的入度for (const node in graph) {for (const neighbor of graph[node]) {inDegree[neighbor]++;}}// 将入度为 0 的节点加入队列for (const node in inDegree) {if (inDegree[node] === 0) {queue.push(node);}}// 处理队列中的节点while (queue.length > 0) {const node = queue.shift(); // 取出队首节点result.push(node);          // 加入拓扑排序结果// 减少相邻节点的入度for (const neighbor of graph[node]) {inDegree[neighbor]--;// 如果相邻节点的入度为 0,加入队列if (inDegree[neighbor] === 0) {queue.push(neighbor);}}}// 检查是否存在环if (result.length !== Object.keys(graph).length) {throw new Error("图中存在环,无法进行拓扑排序");}return result;
}// 示例
const graph = {A: ['C'],B: ['C', 'D'],C: ['E'],D: ['F'],E: ['H', 'F'],F: ['G'],G: [],H: [],
};console.log(kahnTopologicalSort(graph)); // 输出: ['A', 'B', 'D', 'C', 'E', 'F', 'H', 'G']

总结

DAG 是一种强大的数据结构,广泛应用于任务调度、数据流处理、版本控制等领域。其核心优势在于通过拓扑排序解决依赖问题,并通过动态规划高效计算最短/最长路径。理解 DAG 的特性和算法(如拓扑排序、Kahn 算法)对于解决实际工程问题至关重要。

http://www.dtcms.com/a/336967.html

相关文章:

  • 【Langchain系列三】GraphGPT——LangChain+NebulaGraph+llm构建智能图数据库问答系统
  • 15.三数之和
  • InfluxDB 开发工具链:IDE 插件与调试技巧(二)
  • 01.Linux小技巧
  • 从 UI 角度剖析蔬菜批发小程序的设计之道——仙盟创梦IDE
  • STRIDE威胁模型
  • IDE开发系列(1)基于QT的简易IDE框架设计
  • 【P38 6】OpenCV Python——图片的运算(算术运算、逻辑运算)加法add、subtract减法、乘法multiply、除法divide
  • 实践笔记-VSCode与IDE同步问题解决指南;程序总是进入中断服务程序。
  • 面试 TOP101 二叉树专题题解汇总Java版(BM23 —— BM41)
  • 深入解析StatefulSet与K8s服务管理
  • 集成电路学习:什么是Face Detection人脸检测
  • 多线程初阶-线程安全 (面试和工作的重点!!!)
  • Vue2篇——第六章 Vue 路由(VueRouter)全解析
  • Linux系统网络排查工具总结
  • org.apache.kafka.clients 和 org.springframework.kafka 的区别
  • kafka 发送消息有哪些模式?各自的应用场景是什么?
  • Elasticsearch全文检索中文分词:IK分词器详解与Docker环境集成
  • AI编程工具对决:Kilo vs Augment 开发Flutter俄罗斯方块游戏实战对比
  • 【AI论文】UI-Venus技术报告:借助强化微调(RFT)打造高性能用户界面(UI)代理
  • 手写Spring容器核心原理
  • 加密资产投资的六种策略:稳定币合规后的 Web3 投资和 RWA
  • 杂记 05
  • ARM 架构简明教程学习笔记
  • 微信原生小程序的一次gulp构建
  • DevExtreme Angular UI控件更新:引入全新严格类型配置组件
  • Kafka的ISR、OSR、AR详解
  • Rust学习笔记(六)|Rust 中的常用集合(Vector、String、HashMap)
  • Linux网络服务(一)——计算机网络参考模型与子网划分
  • 计算机网络:2、TCP和UDP