起因

最近在项目上实现功能时,遇到了一个需求,需要把一个 excel 里的数据按照一定规则转换成 sql,用的实现方法与之前一篇博客 Attribute + TypeConverter 实现 Excel To Json 中的思想类似,使用 attribute (java 里叫 annotation) 来在 model 上标记 property 与 excel 列名的对应关系,但是在分析 excel 时遇到了更复杂的情况,某一列的验证规则需要基于其他列的值,因此在转换列值的时候需要考虑列与列之间的依赖关系,被依赖的列需要先转换。这就需要一种算法来对列的转换顺序进行排序,把被依赖的列放在转换序列的前面,把有依赖的列放在转换序列的后面,这样只要按照这个转换序列来依次转换所有的列,就不会有问题了,举个例子,假如我的 excel 里有 A B C D 4列,其中 A 列的值在验证时需要 判断 D 列的值,假设 D 的值为 true,需要 A 的值为 1, 假设 D 的值为 false,需要 A 的值为 2,也就是说 A 的值需要 D 的值为前提条件进行判断,所以在转换的时候我们需要先转换 D 后转换 A,因此理想的转换序列应该是 D A B C

从另一个角度说,我们也需要一个算法来检查我的 attribute 里是否出现了由于错误引起的循环依赖问题。还是上面的例子,假如 A 依赖 D 的值, D 依赖 C 的值,C 依赖 A 的值,就形成了一个循环依赖

C -> D -> A -> C

这种情况下是无法进行解析的,应该检查是否有逻辑错误。

在网上搜索时发现 拓扑排序算法 刚好就是用来分析各个任务之间的依赖关系,并且能过分析出各个任务之间有没有循环引用的情况,下面来聊聊拓扑排序算法

什么是拓扑排序

拓扑排序(Topological Sorting)是一种把有向无环图(DAG, Directed Acyclic Graph)转换成线性序列的排序算法,算法的输入是一个 有向无环图,经过算法分析把图中的所有节点按照先后顺序(依赖关系)进行拆解,最后得到一个有顺序的队列,在前(被依赖)的节点靠前,越靠后的节点或有多个节点指向该节点,那这个节点在队列中的位置就越靠后。

看下面这个例子

节点 5 和 4 不依赖任何节点,因此在输出队列里也靠前,而 0 和 1 分别有 2 个依赖的节点,因此需要靠后处理,经过拓扑排序后的结果:

5 4 2 3 1 0

需要注意的是拓扑排序的结果可能不唯一,起点通常是一个入度为 0 的节点

下面两种排序结果都是正确的:

5 4 2 3 1 0

4 5 2 3 0 1

入度

这里出现了一个新的概念–入度,入度指的是以该节点为终点的边的数量

上图的 0 和 1 节点 的入度为 2,5 和 4 的入度为 0,2 和 3 的入度为 1

有向无环图

引自维基百科,在图论中,如果一个有向图从任意顶点出发无法经过若干条边回到该点,则这个图是一个有向无环图(DAG,directed acyclic graph)

有向 指的是节点之间的边是有方向的,从一个节点到另一个节点,例如 A -> B,我们可以理解为 B 对 A有依赖,要完成 B 需要先完成 A。

无环 指的是不存在从一个节点出发,最终又回到当前节点的路径。

回到上面的例子,

C -> D -> A -> C

从 C 出发最后又回到了 C,就形成了一个环,代表出现了循环依赖

算法思路

我们可以把排序的过程看做是解依赖的过程,

把所有没有依赖的节点(入度为 0)放进一个队列

从队列拿出一个节点,从图中拿掉这个节点(相当于这个任务完成了),同时拿掉它指向别的节点的边,把它指向的节点的入度减 1,如果它指向的节点 入度变为 0(没有依赖了),则把该节点放入队列

重复第 2 步,直到所有的节点都从图上拿走

把节点从图上拿走的顺序,就是最终输出的序列

用一张图来表示这个过程,图中的红色数字表示入度

找到入度为 0 的节点 1

拿掉 节点 1,此时 节点 2 的入度变为 0,4 的入度变成 1

拿掉 节点 2,节点 3 的入度变为 1, 节点 4 的入度为 0

拿掉 节点 4,节点 3 的入度为 0,节点 5 的入度为 1

拿掉 节点 3,节点 5 的入度为 0

拿掉 节点 5,结束

最后的输出顺序:

1 2 4 3 5

判断环

如果有环存在,则在不断拿掉点的过程中,出现图上还有节点,但是无法找到入度为 0 的点, 看下面这个图

图中 B-C—E 是一个环,我们看看当只剩 B-C—E 3 个节点时各个节点的入度情况

根据拓扑排序算法,需要找到当前图中所有入度为 0 的节点,依次放入队列并去掉这个节点,把它的边指向的节点入度减 1,但此时 B C E 的入度都为 1,不存在入度为 0 的点,因此算法无法进行下去,所以我们只要判断当入度为 0 的队列为空之后,已经拿掉的节点的个数与原来的节点总个数是否相等,如果相等则表示全部处理完,如果不想等表示有图存在,上图的例子中,拿掉的节点数为 2 (AD),此时图上已经不存在入度为 0 的点,但是顶点总数为 5,与 2 不相等,因此说明图中存在环

算法实现

0

0

vote

Article Rating

拓扑排序 java_[Java]聊聊拓扑排序算法相关推荐

  1. java中的排序方法,Java中的排序比较方式:自然排序和比较器排序

    这里所说到的Java中的排序并不是指插入排序.希尔排序.归并排序等具体的排序算法.而是指执行这些排序算法时,比较两个对象"大小"的比较操作.我们很容易理解整型的 i>j 这样 ...

  2. java冒泡排序找最大的值_(13)數組操作:遍歷、輸出最大值、冒泡排序、選擇排序,java已有的排序方法、折半查找...

    1.數組遍歷 /* * 獲取數組中元素,遍歷 */ int []y=new y[3]; for(int i=0;i { System.out.println("y["+i+&quo ...

  3. acill排序 java_字符串ASCII码排序

    对接第三方渠道的支付API时,三方给的数据签名规则,其中一条是要求参数按照ASCII码从小到大排序. 如下是渠道方有关生成签名规则的java代码示例: //初始化0010merkey.private文 ...

  4. [Leetcode][第207题][JAVA][课程表][拓扑排序][DFS]

    [问题描述][中等] [解答思路] 1. 拓扑排序 复杂度分析 HashSet[] 数组 import java.util.HashSet; import java.util.LinkedList; ...

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

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

  6. 【Java】拓扑排序

    文章目录 1.什么是拓扑排序 2.java实现思路 3.代码实现 4.运行结果 测试用例1(无环) 输入 输出 测试用例2(有环) 输入 输出 1.什么是拓扑排序 对一个有向无环图(Directed ...

  7. 【数据结构】什么是拓扑排序—关于图的拓扑排序

    目录 一.什么是拓扑排序? 二.拓扑排序:基本概念 三.拓扑排序:分析 四.拓扑排序:步骤 五.拓扑排序:实现 六.练习 一.什么是拓扑排序? 对一个有向无环图(Directed Acyclic Gr ...

  8. 希尔排序的java算法_Java算法系列篇 【希尔排序】

    什么? 搞Java不会算法? 由于个人兴趣原因以及工作所需,最近了解Java算法的相关案例 及时分享 感兴趣的欢迎交流 希尔排序 描述: 基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直 ...

  9. java 排序_Java中常见的排序算法有哪些?---选择排序

    排序相关的的基本概念 排序: 将一组杂乱无章的数据按一定的规律顺次排列起来. 数据表( data list): 它是待排序数据对象的有限集合. 排序码(key):通常数据对象有多个属性域, 即多个数据 ...

  10. java中queue排序_Java中常见的排序算法有哪些?---选择排序

    排序相关的的基本概念 排序: 将一组杂乱无章的数据按一定的规律顺次排列起来. 数据表( data list): 它是待排序数据对象的有限集合. 排序码(key):通常数据对象有多个属性域, 即多个数据 ...

最新文章

  1. call_user_func
  2. BERT Word Embeddings Tutorial
  3. skywalking链路追踪在微服务架构中的使用
  4. JSP——JavaBean应用
  5. 如何展示富文本_自助建站如何做出个性化效果?
  6. 领域驱动设计 (DDD)实例分析
  7. 消消乐实现下坠_手把手教你如何实现iOS消消乐小游戏Demo
  8. Linux移植随笔:又遇困难
  9. gnome桌面环境 kde桌面环境的区别
  10. 查找交换机某端口连接的主机IP地址
  11. Javascript游戏,街头霸王
  12. django连接mysql
  13. 一位全减器VHDL语言
  14. Time Shift 与 Record 功能的区别
  15. 一起学爬虫(Python) — 19 年轻人,进来学自动化
  16. 计算机组成原理实验报告一静态随机存储器
  17. error:control reaches end of non-void function [-Werror=return-type]
  18. SQL文件切割工具、大文件操作工具
  19. 孟:解密获取网站访客QQ号码的方法及原理
  20. Java中接口的作用,为什么要写接口?

热门文章

  1. 深度linux操作系统
  2. Unity3D学习笔记——物理引擎
  3. 打游戏用什么蓝牙耳机好?英雄联盟手游推荐蓝牙耳机
  4. ubuntu修改IP后无法正常上网的解决
  5. codeblock的汉化过程
  6. 支持html签名的邮箱app,在iPhone和iPad上创建使用丰富的HTML电子邮件签名 | MOS86
  7. Altova XMLSpy2011的破解出现的问题
  8. Django官方中文文档
  9. django-redis 中文文档
  10. 连接linux工具Mtr,Mac、linux和windows mtr路径探测工具安装使用