前言:

在实际工作场景中用到了拓扑排序,遂记录下来以供参考理解。

拓扑排序介绍:

首先,拓扑排序区别于一般的数值类排序算法,如冒泡排序、快速排序、堆排序等。它的处理对象是有向无环图DAG,最终是把有向无环图转换成一个有顺序的列表。

拓扑排序实际应用场景:

在实际应用场景中,需要对数据进行一个ETL处理,具体处理流程类似下图:

        由于在ETL过程中存在流程的依赖顺序关系,如“数据join操作2”执行前必须要先进行第一次数据join操作和接入数据表C,否则ETL流程不成功,由此在实际执行过程中就需要对此类流程图进行排序,最终将其转换为从左到右的顺序正常执行。

那么在排序过程中本质上就是一个拓扑排序,把每一个流程处理框看成一个顶点,流程框之间有向连接线作为顶点之间的边。按照其拓扑排序后,结果可能是1--2--3--4--5--6,或者是2--1--3--4--5--6,或者是2--1--4--3--5--6等共计6种排序结果。

最终的顺序取决于实际算法中用到的排序方法,但是无论是以上罗列出的哪种顺序,都能保证整个流程可以正常的执行。

拓扑排序实现原理:

0.定义一个最终结果List集合resultList;

1.将上述一个流程实际节点的属性集合定义为一个java类DefinedNode(其中包含该节点依赖的下一个节点集合,该节点入度,节点业务特有的属性

2.每个节点都有一个唯一id,并用NodeMap来存储整个流程每个节点的数据,存储数据为<nodeId,DefinedNode>;

        3.遍历map集合,找出节点中入度为0(即没有被依赖)的节点放入栈stack中;

4.遍历栈中元素,取出栈元素添加到resultList集合中,找到和它有关联的节点并将其关联的节点入度减1;

5.其关联的节点如果减1后入度为0,则添加到栈stack中;

6.重复4.5步,直到栈中不存在元素为止;

此时,返回的resultList集合就是排序后结果,此时resultList中集合对象可能为④--②--①--③--⑤--⑥,即整个流程最终按照resultList中对象顺序执行。

由于具体业务场景各有不同,在此仅写一个通用的用例来说明。

public class DAGSortTest {static class DefinedNode{int id;//节点idint inValue;//节点入度值List<Integer> nextIds;//下一个节点id集合public DefinedNode(int id, int inValue, List<Integer> nextIds) {this.id = id;this.inValue = inValue;this.nextIds = nextIds;}public int getId() {return id;}public int getInValue() {return inValue;}public List<Integer> getNextIds() {return nextIds;}}public static void main(String[] args) {Map<Integer, DefinedNode> nodeMaps = initDefinedNodeMap();List<DefinedNode> resultList = DagSort(nodeMaps);for (DefinedNode definedNode : resultList) {System.out.println(definedNode.getId());}}private static Map<Integer, DefinedNode> initDefinedNodeMap() {Map<Integer, DefinedNode> nodeMaps = new HashMap<>();List<Integer> nextIds1 = new ArrayList<>();nextIds1.add(3);DefinedNode node1 = new DefinedNode(1,0,nextIds1);nodeMaps.put(1,node1);List<Integer> nextIds2 = new ArrayList<>();nextIds2.add(3);DefinedNode node2 = new DefinedNode(2,0,nextIds2);nodeMaps.put(2,node2);List<Integer> nextIds3 = new ArrayList<>();nextIds3.add(5);DefinedNode node3 = new DefinedNode(3,2,nextIds3);nodeMaps.put(3,node3);List<Integer> nextIds4 = new ArrayList<>();nextIds4.add(5);DefinedNode node4 = new DefinedNode(4,0,nextIds4);nodeMaps.put(4,node4);List<Integer> nextIds5 = new ArrayList<>();nextIds5.add(6);DefinedNode node5 = new DefinedNode(5,2,nextIds5);nodeMaps.put(5,node5);List<Integer> nextIds6 = new ArrayList<>();DefinedNode node6 = new DefinedNode(6,1,nextIds6);nodeMaps.put(6,node6);return nodeMaps;}public static List<DefinedNode> DagSort(Map<Integer,DefinedNode> nodeMaps){List<DefinedNode> resultList = new ArrayList<>();Stack<DefinedNode> stack = new Stack();for (DefinedNode definedNode : nodeMaps.values()) {if (definedNode.getInValue()==0){stack.push(definedNode);}}while (!stack.empty()){DefinedNode definedNode = stack.pop();resultList.add(definedNode);List<Integer> nextIds = definedNode.getNextIds();for (Integer nextId : nextIds) {DefinedNode nextNode = nodeMaps.get(nextId);if (nextNode.getInValue()-1==0){stack.push(nextNode);}else {nodeMaps.put(nextNode.getId(),new DefinedNode(nextNode.getId(),nextNode.getInValue()-1,nextNode.getNextIds()));}}}return resultList;}}

最终运行结果如下:

拓扑排序在实际项目中应用相关推荐

  1. 排个课表学会了拓扑排序!有点意思

    原创不易,帅哥美女呢请三连支持一波 前言 大家好,我是bigsai. 拓扑排序,很多人都可能听说但是不了解的一种算法.不知者大多会提出这样的疑问: 这是某种排序算法?这好像是一种图论算法?图也能排序? ...

  2. 拓扑排序:如何确定代码源文件的编译依赖关系

    什么是拓扑排序? 由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序 拓扑排序有何应用? 我们知道,一个完整的项目往往会包含很多代码源文件.编译器在编译整个项目的时候,需要按照依赖关 ...

  3. 对给定的AOV网络,产生所有的拓扑排序结果,并进行解法的动态演示

    数据结构 课程实验报告 实验题目: 33题,对给定的AOV网络,产生所有的拓扑排序结果,并进行解法的动态演示. 实验学时:一周 实验日期: 实验目的:对给定AOV网络,产生所有的拓扑排序结果,并进行动 ...

  4. 数据结构(六):图的概念、存储方式、基本操作、最小生成树、最短路径、有向无环图、关键路径 | Prim、Kruskal算法 | BFS、Dijkstra、Floyd算法 | 拓扑排序 | 求关键路径

    文章目录 第六章 图 一.图 (一)图的定义 (二)图逻辑结构的应用 (三)无向图.有向图 (四)简单图.多重图 (五)顶点的度.入度.出度 (六)顶点-顶点的关系描述 (七)连通图.强连通图 (八) ...

  5. 拓扑排序和关键路径的图形化显示

    资源下载地址:https://download.csdn.net/download/sheziqiong/85883662 资源下载地址:https://download.csdn.net/downl ...

  6. 拓扑排序之java实现_有向图和拓扑排序Java实现

    package practice; import java.util.ArrayDeque; import java.util.Iterator; import java.util.Stack; pu ...

  7. C/C++二级指针概念及应用(有向图的邻接表(拓扑排序)、有向网图的邻接表、树的孩子表示)

    目录 一.概述 例1: 例2: 代码: 二.实例 1.有向图的邻接表(拓扑排序) 2.有向网图的邻接表 3.树的孩子表示 一.概述 二级指针:指向指针的指针.一般需要修改地址的时候会用到二级指针. 注 ...

  8. 0x21.搜索 - 树与图的遍历、拓扑排序

    目录 一.树与图的深度优先遍历及树的一些性质 1.树与图的深度优先遍历 2.时间戳 3.树的DFS序(树链剖分前驱知识) 4.树的深度 5.树的重心与sizesizesize 6.图的连通块划分 二. ...

  9. 【zz】如何去理解 拓扑排序算法

    from http://www.cnblogs.com/shanyou/archive/2006/11/16/562861.html 查看Castle的代码,在Castle.Core中内部的数据结构采 ...

最新文章

  1. 【MongoDB异常】Exception authenticating MongoCredential解决方法
  2. Altium designer中高亮元器件或网络时对比度调节
  3. linux 内核 ntfs,Linux大脑 内核 内核编译(NTFS)
  4. 连接CPU和计算机的总线,什么是计算机总线 总线和接口的区别
  5. iOS开发-retain/assign/strong/weak/copy/mutablecopy/autorelease区别
  6. matlab 高级函数 —— circshift、squeeze
  7. 固态硬盘和机械硬盘的区别(7大区别,简单易懂)
  8. Java休眠睡眠方法
  9. Java基础知识——IO流
  10. C++-计算体质指数BMI值 信息学奥赛
  11. 2020再谈软件测试人员的核心竞争力
  12. h = a –bqc线性最小二乘问题 c语言,物理实验之最小二乘法 | 怎样学习大学物理小组 | 果壳网 科技有意思...
  13. The 2021 ICPC Asia Shanghai Regional Programming Contest D、E
  14. 2022-2027年中国大米蛋白粉行业市场全景评估及发展战略规划报告
  15. 角速度求积分能得到欧拉角吗_数值计算方法 第六章 数值积分和数值微分
  16. Stacks of Flapjacks UVA 薄饼排序问题
  17. 刷新token重新请求接口
  18. PowerDesigner经验,sql文件生成pdm文件,并生成中文comment描述
  19. Java 自定义注解实现springMVC 参数校验非空判断,为空 则返回响应为空信息
  20. MHCHXM超快恢复二极管SF1604为什么是三个脚

热门文章

  1. 丁磊、马云、马化腾的个性差异
  2. 静下心来的刘强东太可怕!三个月,京东市值重回巅峰!
  3. shopify开发经验
  4. NOIP2017day2题解
  5. /Zc:strictStrings配置
  6. 程序员之间的鄙视链-2022.10.04
  7. (一)傅里叶变换:傅里叶级数(Fourier Series)
  8. 实现仿若依后台管理主要功能
  9. Scikit-learn学习系列 | 4. sklearn特征降维方法汇总(方差过滤,卡方,F过滤,互信息,嵌入法)
  10. 博应用测评软件ofo小黄车和摩拜单车哪个更好骑