大数据工作流任务调度--有向无环图(DAG)之拓扑排序
点击上方蓝字关注DolphinScheduler(海豚调度)
|作者:代立冬
|编辑:闫利帅
回顾基础知识:
图的遍历
图的遍历是指从图中的某一个顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次且仅访问一次。
注意树是一种特殊的图,所以树的遍历实际上也可以看作是一种特殊的图的遍历
图的遍历主要有两种算法
广度优先搜索(Breadth First Search,BFS)
深度优先搜索的搜索策略是尽可能深地搜索一个图。基本思想是:首先访问图中某一未访问的顶点V1,然后由V1出发,访问与V1邻接且未被访问的任一顶点V2,再访问与V2邻接且未被访问的任一顶点V3,……重复上述过程。当不能再继续向下访问(即孤立点)时,依次退回到最近被访问的顶点,若它还有邻接顶点未被访问过,则从该点开始继续上述搜索过程,直到图中所有顶点均被访问过为止。
深度优先搜索(Depth First Search,DFS)
广度优先搜索的基本思想是:首先访问起始顶点v,接着由v出发,依次访问v的各个未访问过的邻接顶点w1,w2,…,wi,然后再依次访问w1,w2,…,wi的所有未被访问过的邻接顶点;再从这些访问过的顶点出发,再访问它们所有未被访问过的邻接顶点……依次类推,直到图中所有顶点都被访问过为止。
举例说明
如下图,如果采用 广度优先搜索(BFS)遍历如下 1 2 5 3 4 6 7,如果采用深度优先搜索(DFS)遍历如下 1 2 3 4 5 6 7。
拓扑排序(Topological Sorting)
维基百科上拓扑排序的定义为
对于任何有向无环图(Directed Acyclic Graph,DAG)而言,其拓扑排序为其所有结点的一个线性排序(同一个有向图可能存在多个这样的结点排序)。该排序满足这样的条件——对于图中的任意两个结点U和V,若存在一条有向边从U指向V,则在拓扑排序中U一定出现在V前面。
通俗来讲:拓扑排序是一个有向无环图(DAG)的所有顶点的线性序列, 该序列必须满足两个条件
每个顶点出现且只出现一次。
若存在一条从顶点A到顶点B的路径,那么在序列中顶点 A出现在顶点 B的前面。
如何找出它的拓扑排序呢?这里说一种比较常用的方法:
在介绍这个方法之前有必要补充下有向图结点的入度(indegree)和出度(outdegree)的概念。假设有向图中不存在起点和终点为同一结点的有向边,则:
入度:设有向图中有一结点V,其入度即为当前所有从其他结点出发,终点为V的的边的数目。也就是所有指向V的有向边的数目。
出度:设有向图中有一结点V,其出度即为当前所有起点为V,指向其他结点的边的数目。也就是所有由V发出的边的数目。
从DAG图中选择一个入度为0的顶点并输出。
从图中删除该顶点和所有以它为起点的有向边。
重复1和2直到当前的DAG图为空或当前图中不存在入度为0的顶点为止。后一种情况说明有向图中必然存在环。
例如下面这个DAG图:
结点1的入度:0,出度:2
结点2的入度:1,出度:2
结点3的入度:2,出度:1
结点4的入度:2,出度:2
结点5的入度:2,出度:0
它的拓扑排序流程为:
于是,得到拓扑排序后的结果是: {1,2,4,3,5} 。
如果没有结点2 —> 结点4的这个箭头,那么如下:
我们可以得到它的拓扑排序为:{1,2,4,3,5} 或者 {1,4,2,3,5} ,即对同一DAG图来说,它的拓扑排序结果可能存在多个。
拓扑排序主要用来解决有向图中的依赖问题。
在讲到实现的时候,有必要插以下内容:
由此我们可以进一步得出一个改进的深度优先遍历或广度优先遍历算法来完成拓扑排序。以广度优先遍历为例,这一改进后的算法与普通的广度优先遍历唯一的区别在于我们应当保存每一个结点对应的入度,并在遍历的每一层选取入度为0的结点开始遍历(而普通的广度优先遍历则无此限制,可以从该吃呢个任意一个结点开始遍历)。这个算法描述如下:
初始化一个Map或者类似数据结构来保存每一个结点的入度。
对于图中的每一个结点的子结点,将其子结点的入度加1。
选取入度为0的任意一个结点开始遍历,并将该节点加入输出。
对于遍历过的每个结点,更新其子结点的入度:将子结点的入度减1。
重复步骤3,直到遍历完所有的结点。
如果无法遍历完所有的结点,则意味着当前的图不是有向无环图。不存在拓扑排序。
广度优先遍历拓扑排序的核心Java代码如下:
public class TopologicalSort {
/**
* 判断是否有环及拓扑排序结果
*
* 有向无环图(DAG)才有拓扑(topological)排序
* 广度优先遍历的主要做法:
* 1、遍历图中所有的顶点,将入度为0的顶点入队列。
* 2、从队列中poll出一个顶点,更新该顶点的邻接点的入度(减1),如果邻接点的入度减1之后等于0,则将该邻接点入队列。
* 3、一直执行第2步,直到队列为空。
* 如果无法遍历完所有的结点,则意味着当前的图不是有向无环图。不存在拓扑排序。
*
*
* @return key返回的是状态, 如果成功(无环)为true, 失败则有环, value为拓扑排序结果(可能是其中一种)
*/
private Map.Entry<Boolean, List<Vertex>> topologicalSort() {
//入度为0的结点队列
Queue<Vertex> zeroIndegreeVertexQueue = new LinkedList<>();
//保存结果
List<Vertex> topoResultList = new ArrayList<>();
//保存入度不为0的结点
Map<Vertex, Integer> notZeroIndegreeVertexMap = new HashMap<>();
//扫描所有的顶点,将入度为0的顶点入队列
for (Map.Entry<Vertex, VertexInfo> vertices : verticesMap.entrySet()) {
Vertex vertex = vertices.getKey();
int inDegree = getIndegree(vertex);
if (inDegree == 0) {
zeroIndegreeVertexQueue.add(vertex);
topoResultList.add(vertex);
} else {
notZeroIndegreeVertexMap.put(vertex, inDegree);
}
}
//扫描完后,没有入度为0的结点,说明有环,直接返回
if(zeroIndegreeVertexQueue.isEmpty()){
return new AbstractMap.SimpleEntry(false, topoResultList);
}
//采用topology算法, 删除入度为0的结点和它的关联边
while (!zeroIndegreeVertexQueue.isEmpty()) {
Vertex v = zeroIndegreeVertexQueue.poll();
//得到相邻结点
Set<Vertex> subsequentNodes = getSubsequentNodes(v);
for (Vertex subsequentVertex : subsequentNodes) {
Integer degree = notZeroIndegreeVertexMap.get(subsequentVertex);
if(--degree == 0){
topoResultList.add(subsequentVertex);
zeroIndegreeVertexQueue.add(subsequentVertex);
notZeroIndegreeVertexMap.remove(subsequentVertex);
}else{
notZeroIndegreeVertexMap.put(subsequentVertex, degree);
}
}
}
//notZeroIndegreeVertexMap如果为空, 表示没有环
AbstractMap.SimpleEntry resultMap = new AbstractMap.SimpleEntry(notZeroIndegreeVertexMap.size() == 0 , topoResultList);
return resultMap;
}
}
注意输出结果是该图的拓扑排序序列之一。
每次在入度为0的集合中取顶点,并没有特殊的取出规则,取顶点的顺序不同会得到不同的拓扑排序序列(如果该图有多种排序序列)。
由于输出每个顶点的同时还要删除以它为起点的边。如果图有V个顶点,E条边,则一般该算法的时间复杂度为O(V+E)。这里实现的算法最终key返回的是状态, 如果成功(无环)为true, 失败则有环, 无环时value为拓扑排序结果(可能是其中一种)。注意输出结果是该图的拓扑排序序列之一。每次在入度为0的集合中取顶点,并没有特殊的取出规则,取顶点的顺序不同会得到不同的拓扑排序序列(如果该图有多种排序序列)。
由于输出每个顶点的同时还要删除以它为起点的边。如果图有V个顶点,E条边,则一般该算法的时间复杂度为O(V+E)。这里实现的算法最终key返回的是状态, 如果成功(无环)为true, 失败则有环, 无环时value为拓扑排序结果(可能是其中一种)。
他们正在使用Apache DolphinScheduler
欢迎在此处阅读原文,点star收藏
大数据工作流任务调度--有向无环图(DAG)之拓扑排序的更多相关文章
- 第十二届湖南省赛 (B - 有向无环图 )(拓扑排序+思维)好题
Bobo 有一个 n 个点,m 条边的有向无环图(即对于任意点 v,不存在从点 v 开始.点 v 结束的路径). 为了方便,点用 1,2,…,n 编号. 设 count(x,y) 表示点 x 到点 y ...
- C#实现有向无环图(DAG)拓扑排序
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在 ...
- 【模板整合计划】图论—有向无环图 (DAG) 与树
[模板整合计划]图论-有向无环图 (DAG) 与树 一:[拓扑排序] 最大食物链计数 \(\text{[P4017]}\) #include<cstring> #include<cs ...
- 判断有向无环图(DAG)
1.拓扑排序 bfs 所有入度为0的先入选. 2.tarjan 1个点1个集合 3.暴力 一个点不能重新到达自己
- [笔记] 有向无环图 DAG
最小链覆盖 (最长反链) 最小链覆盖 \(=n-\) 最大匹配. 考虑首先每个点自成一条链,此时恰好有 \(n\) 条链,最终答案一定是合并(首尾相接)若干条链形成的. 将两点匹配的含义其实就是将链合 ...
- 【拓扑】【宽搜】CSU 1084 有向无环图 (2016湖南省第十二届大学生计算机程序设计竞赛)
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1804 题目大意: 一个有向无环图(DAG),有N个点M条有向边(N,M<=105 ...
- JavaScript + SVG实现Web前端WorkFlow工作流DAG有向无环图
一.效果图展示及说明 (图一) (图二) 附注说明: 1. 图例都是DAG有向无环图的展现效果.两张图的区别为第二张图包含了多个分段关系.放置展示图片效果主要是为了说明该例子支持多段关系的展现(当前也 ...
- select 函数实现 三种拓扑结构 n个客户端的异步通信 (完全图+线性链表+无环图)
一.这里只介绍简单的三个客户端异步通信(完全图拓扑结构) //建立管道 mkfifo open顺序: cl1 读 , cl2 cl3 向 cl1写 cl2 读 , cl1 cl3 向 cl2写 cl3 ...
- 算法精解:DAG有向无环图
DAG是公认的下一代区块链的标志.本文从算法基础去研究分析DAG算法,以及它是如何运用到区块链中,解决了当前区块链的哪些问题. 关键字:DAG,有向无环图,算法,背包,深度优先搜索,栈,BlockCh ...
随机推荐
- ZIP压缩输入/输出
学习内容: 一.压缩文件 1.利用ZipOutputStream类对象,可将文件压缩. 2.ZipOutputStream类构造方法:ZipOutputStream(OutputStream out) ...
- python文件操作拓展与认识函数
目录 文件内光标的移动(了解即可) 前言 控制光标移动seek()方法 文件的修改 函数 语法结构 简单的使用 作业 答案 文件内光标的移动(了解即可) 前言 在文件的内置方法中,read()方法是可 ...
- pandas:数据迭代、函数应用
1.数据迭代 1.1 迭代行 (1)df.iterrows() for index, row in df[0:5].iterrows(): #需要两个变量承接数据 print(row) print(& ...
- Django+Vue+Nginx+Https域名代理访问
Django+Vue使用Nginx实现Https域名的安全访问 前端 VUE 前端访问自身域名: https://demo.com,后序使用 Nginx 代理至后端 直接访问后端https:api会无 ...
- PHP odbc查询SQL SERVER数据库带有中文时无返回数据
近日遇到一个小麻烦当数据库中有中文字符数据 结果odbc_fetch_array后 我用json_encode怎么也得不到数据页面一片空白 我脑子也一片空白后来才知道sqlserver 没有 UTF- ...
- 南京大学 静态软件分析(static program analyzes)-- introduction 学习笔记
一.Programming Languages体系 静态程序分析是编程语言中应用层面下的一个细分领域,它是一个非常重要的核心内容. 在理论部分,考虑的是如何设计一个语言的语法和语义,如何设计语言的类型 ...
- Snowflake(雪花算法),什么情况下会冲突?
文章首发在公众号(龙台的技术笔记),之后同步到博客园和个人网站:xiaomage.info 分布式系统中,有一些需要使用全局唯一 ID 的场景,这种时候为了防止 ID 冲突可以使用 36 位的 UUI ...
- Moriis神级遍历!
Moriis 遍历 Morris 遍历是二叉树遍历的一种方式,传统的递归和非递归遍历的时间复杂的都是O(N),空间复杂度都是O(h)(h为树的高度),而 Morris 遍历可以做到时间复杂的依然为 O ...
- 阿里云体验有奖:使用PolarDB-X与Flink搭建实时数据大屏
体验简介 场景将提供一台配置了CentOS 8.5操作系统的ECS实例(云服务器).通过本教程的操作带您体验如何使用PolarDB-X与Flink搭建一个实时数据链路,模拟阿里巴巴双十一GMV大屏. ...
- HMS Core音频编辑服务3D音频技术,助力打造沉浸式听觉盛宴
2022年6月28日,HDD·HMS Core.Sparkle影音娱乐沙龙在线上与开发者们见面.HMS Core音频编辑服务(Audio Editor Kit)专家为大家详细分享了基于分离的3D音乐创 ...