首页 > 编程语言 >有向无环图(DAG,Directed Acyclic Graph)算法

有向无环图(DAG,Directed Acyclic Graph)算法

时间:2024-11-24 17:01:15浏览次数:12  
标签:Directed DAG Graph 拓扑 add 任务 依赖 graph 排序

大家好!今天我想给大家讲一个非常有趣的算法,叫做有向无环图(DAG,Directed Acyclic Graph)算法。这个算法就像是在玩一个游戏,帮我们找到完成一系列任务的最佳顺序!

什么是有向无环图?

假设你喜欢做一些手工DIY,比如制作一个纸飞机。但你发现,做纸飞机需要先完成一些步骤,比如剪纸、折纸、贴胶带等。每个步骤都有一些依赖关系,比如你得先剪好纸,才能折飞机;你得先折好飞机的基本形状,才能贴胶带。这些步骤之间的关系可以用一个有向无环图来表示。每个步骤是一个点,步骤之间的依赖关系用箭头来表示。

DAG的常见应用

  • 任务调度:像上面提到的任务依赖关系,DAG可以帮助我们找出完成所有任务的最短时间。
  • 拓扑排序:这是一种把所有任务排成一列的方法,使得每个任务都在它依赖的任务之后。
  • 依赖解析:比如在软件编译中,DAG可以帮助解析和管理代码模块之间的依赖关系。
  • 数据处理:在数据流中,DAG可以表示数据的处理步骤和依赖关系。

拓扑排序算法

拓扑排序就像是排队打游戏机,确保每个人都按顺序来玩。以下是拓扑排序的步骤:

  1. 选择一个入度为0的顶点:也就是没有其他任务依赖它的任务。这意味着这个任务可以先完成。

  2. 移除这个顶点及其所有的出边:因为这个任务已经完成,可以从图中移除。

  3. 重复步骤1和2:直到图中所有任务都被移除。

Java实现拓扑排序

下面是一个用Java实现的简单拓扑排序算法:

import java.util.*;

public class TopologicalSort {

    public static List<Integer> topologicalSort(List<List<Integer>> graph) {
        int n = graph.size();
        List<Integer> result = new ArrayList<>();
        int[] inDegree = new int[n];

        // 计算每个顶点的入度
        for (List<Integer> edges : graph) {
            for (int to : edges) {
                inDegree[to]++;
            }
        }

        // 初始化一个队列来存储入度为0的顶点
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }

        // 执行拓扑排序
        while (!queue.isEmpty()) {
            int vertex = queue.poll();
            result.add(vertex);

            // 移除当前顶点的所有出边
            for (int to : graph.get(vertex)) {
                if (--inDegree[to] == 0) {
                    queue.offer(to);
                }
            }
        }

        // 如果结果列表的大小不等于顶点数,说明图中存在环路
        if (result.size() != n) {
            throw new IllegalStateException("Graph contains a cycle");
        }

        return result;
    }

    public static void main(String[] args) {
        // 示例图:顶点数量为6,边如下
        List<List<Integer>> graph = new ArrayList<>();
        for (int i = 0; i < 6; i++) {
            graph.add(new ArrayList<>());
        }
        graph.get(5).add(2);
        graph.get(5).add(0);
        graph.get(4).add(0);
        graph.get(4).add(1);
        graph.get(3).add(1);
        graph.get(2).add(3);

        List<Integer> sorted = topologicalSort(graph);
        System.out.println("拓扑排序结果: " + sorted);
    }
}

解释

  • 初始化:首先,我们计算每个任务的入度,即有多少个任务依赖它。
  • 队列:然后,我们把所有入度为0的任务放入一个队列中,就像是排队等着玩游戏机的人。
  • 排序:从队列中取出一个任务,加入结果列表,并移除这个任务的所有出边。如果某个任务的入度因此变为0,就意味着它可以开始玩游戏了,我们把它加入队列。
  • 检查环路:如果所有任务都已被移除,那么结果列表的大小应该等于任务数;否则,图中存在环路。

这个算法确保了在DAG中,任务的执行顺序是合理的,不会出现先执行依赖的任务的情况。

完整案例

让我们来看一个具体的例子吧。假设我们要完成以下任务:

  1. 穿鞋子
  2. 出门
  3. 准备食材
  4. 煮饭
  5. 洗碗
  6. 吃晚饭

其中任务之间的依赖关系如下:

  • 穿鞋子 -> 出门
  • 准备食材 -> 煮饭
  • 煮饭 -> 吃晚饭
  • 吃晚饭 -> 洗碗

我们可以用拓扑排序算法来找出这些任务的最佳执行顺序:

  1. 准备食材(没有依赖)
  2. 穿鞋子(没有依赖)
  3. 煮饭(依赖准备食材)
  4. 吃晚饭(依赖煮饭)
  5. 出门(依赖穿鞋子)
  6. 洗碗(依赖吃晚饭)

通过拓扑排序,我们可以得到一个合理的执行顺序,确保所有任务都能顺利完成。

希望这个关于有向无环图算法的分享能帮助大家理解DAG的基本概念和应用。如果大家对这个算法或者其他图论算法有任何问题,欢迎在评论区讨论或者分享你们自己的理解!

标签:Directed,DAG,Graph,拓扑,add,任务,依赖,graph,排序
From: https://blog.csdn.net/m0_58067066/article/details/144001028

相关文章

  • oval-graph 可以和哪些漏洞管理工具集成?
    以下是一些oval-graph可以集成的漏洞管理工具:OpenVAS:OpenVAS是一个开源的漏洞扫描工具,能够扫描网络设备、操作系统、应用程序等,识别潜在的安全漏洞,并提供修复建议。oval-graph可与OpenVAS集成,将OpenVAS扫描出的漏洞数据以图形化的方式展示,帮助安全人员更直观地分析漏......
  • Regular graph and line graph (正则图和线图)(一)
    (1)正则图的定义:如果一个图的每个顶点的度数都是,则称这个图是正则的。(2)正则图的性质:命题1、命题2和推论1命题1:设是度正则图,则:是的特征值;如果是连通的,那么的重数为1;对于的任何特征值,我们有.命题2:矩阵属于邻接代数当且仅当是正则连通图.推论1:设是阶正则连通图,设的不同特征......
  • EChart关系图-GraphLifeExpectancy,附视频讲解与代码下载
    引言: 关系图(或称网络图、关系网络图)在数据可视化中扮演着至关重要的角色。它们通过节点(代表实体,如人、物体、概念等)和边(代表实体之间的关系或连接)的形式,直观地展示了数据集中各元素之间的复杂关联。本文将详细介绍如何使用ECharts库实现一个关系图,包括图表效果预览、视频讲解......
  • LangGraph 源码分析 | BaseTool 模板类
    文章目录BaseTool源码分析核心属性以`TavilySearchResults(BaseTool)`为例namedescriptionargs_schemaresponse_format查询选项属性需要子类实现的抽象方法以`TavilySearchResults(BaseTool)`为例核心方法`arun()`:`run()`的异步执行版本`invoke()`和`ainvoke()`......
  • Contextualization Distillation from Large Language Model for Knowledge Graph Com
    文章目录题目摘要简介相关工作语境化提取实验结论限制附录题目用于知识图完成的大型语言模型的语境化提取论文地址:https://aclanthology.org/2024.findings-eacl.32/项目地址:https://github.com/davidli0406/contextulization-Distillation摘要    ......
  • 配置GraphRAG索引
    配置GraphRAG索引GraphRAG系统具有高度的可配置性。本页概述了GraphRAG索引引擎的可用配置选项。默认配置模式默认配置模式是开始使用GraphRAG系统的最简单方式。它设计为开箱即用,只需最少的配置。索引引擎管道的主要配置部分如下所述。在默认配置模式下设置GraphRAG的主......
  • P11022 「LAOI-6」Yet Another Graph Coloration Problem
    P11022「LAOI-6」YetAnotherGraphColorationProblem-洛谷|计算机科学教育新生态(luogu.com.cn)关于无解情况,如果这个图有两块连通块,那么不可能同时有黑色白色,假设\(1,2\)连通块,设\(1\)中有黑色,因为\(2\)中点不能到\(1\),所以\(2\)中只能是黑色,又因为\(2\)中......
  • GeoKR系列--Geographical Knowledge-Driven Representation Learning for Remote Sens
    一、abstract1.绝大多数遥感图像仍未标注,想要充分利用这些未标注的图像,本文提出了一种基于地理知识驱动的表示学习方法,使得提升遥感图像的网络性能+减少对标注数据的需求。2.本文将全球地表覆盖产品和与每张遥感图像相关的地理位置视为地理知识,为了消除遥感图像与地理知识之......
  • Hidden Bipartite Graph
    HiddenBipartiteGraph题意交互题。有一个\(n\le600\)的图,你可以询问至多\(20000\)次。每次问一个点集\(S\),返回满足两个端点都在\(S\)中的边的个数。你需要判断这个图是不是二分图,如果是,则分别输出左部和右部的点,否则按顺序输出任意一个奇环。思路先判断二分图。一......
  • CF 1805 D. A Wide, Wide Graph (*1800) 思维 + 树的直径
    CF1805D.AWide,WideGraph(*1800)思维+树的直径题目链接题意:思路:若当前点到最远的点的距离\(<k\),说明\(x\)自己成为一个联通块。并且我们知道距离任意一点最远的点一定是树直径的一个端点。反之,则与直径端点在同一个联通块。所以一个点要么独立成为联通块......