因为公司的某个系统比较古老,里面的 job 的管理几乎都是直接通过操作数据库来实现的,对于一般的操作还可以忍受,但是每次想知道 job 之间的依赖关系的时候,就会相当难受,于是便脑袋很抽地一定要写一个查询系统能快速查询 job 之间的依赖关系。

分析

在项目开始之前,大概稍微估算了一下难点,大概可以分为以下两点:

如何在前端显示该依赖图
如何提高查询效率

此篇文章只看第一个问题,由于是本人是前端渣,于是只能去网上搜相应图形显示插件。

前端插件选择

找了很久,终于在 echarts 上找到了一个稍微适合自己的图形插件了,

http://echarts.baidu.com/examples/editor.html?c=graph-simple

不过,这个插件只是一个简单图的插件,也就是说这个插件并不会帮你进行自动定位相应的点,我们需要自己确定各个点的坐标。

解决方案

通过观察发现,该插件上的坐标只需要确定相对坐标就行了,它会根据相对位置进行自动定位,于是感觉瞬间轻松了许多。

仔细思考,发现 job 之间的依赖关系是一个有向无环图,于是开始构思。

要求:

将点按层次显示,保证前面层的点只依赖后面层的点 (同一层也禁止存在依赖关系)。
使得图尽可能整洁,尽量减少线段之间的交叉

解决方案:

通过拓扑排序来实现点的层次选择,每次将所有入度为 0 的点分为同一层即可
通过与前面层的点之间的关系设置相应的权重,同层之间根据权重来排序。我记得好像可以通过动态规划得到最优解的,不过实现起来太麻烦了,就算了

代码如下:

import java.util.*;* 作用: 绘制有向无环图(DAG图)** 说明:* 配合Echarts的simple graph使用,地址见http://echarts.baidu.com/examples/editor.html?c=graph-simple* 用来进行点的坐标定位** 使用条件: 图必须是一个有向无环图(DAG图)** 调用方式: return new DagGraphUtil(points, links).drawDagGraph()** 参数:* points的格式为 ['点1','点2','点3','点4']* links的格式为 [{"source":"点1","target":"点2"},{"source":"点2","target":"点3"},{"source":"点3","target":"点4"}]** 返回结果:* {*     "points": [{"name": "点1","x":100,"y":100},{"name":"点2","x":200,"y":200}, ...],*     "links": [{"source":"点1","target":"点2"},{"source":"点2","target":"点3"}, ...]* }*** 主要算法: 拓扑排序*/
public class  {private final int MAX_LENGTH_X = 900;private final int MAX_LENGTH_Y = 1000;private int maxX;private Map<String, Integer> toNum;private Map<String, Integer> xPosition;private Map<String, Integer> yPosition;private Map<String, Integer> pointWeight;private List<Integer> ySize;private List<String> points;private List<Map<String, String>> links;public (List<String> points, List<Map<String, String>> links) {this.points = points;this.links = links;toNum = new HashMap<>(points.size());xPosition = new HashMap<>(points.size());yPosition = new HashMap<>(points.size());pointWeight = new HashMap<>(points.size());maxX = 0;ySize = new ArrayList<>();for (String point : points) {toNum.put(point, 0);pointWeight.put(point, 0);}for (Map<String, String> link : links) {String toPoint = link.get("target");addMapValue(toNum, toPoint, 1);}}public Map<String, Object> drawDagGraph() {Map<String, Object> result = new HashMap<>(3);dfs(0);List<Map<String, Object>> pList = new ArrayList<>(points.size());for (String point : points) {int xUnitLength = MAX_LENGTH_X / maxX;int x = xPosition.get(point) * xUnitLength + xUnitLength / 2;int yUnitLength = MAX_LENGTH_Y / ySize.get(xPosition.get(point));int y = yPosition.get(point) * yUnitLength + yUnitLength / 2;Map<String, Object> map = new HashMap<>(3);map.put("name", point);map.put("x", x);map.put("y", y);pList.add(map);}result.put("points", pList);result.put("links", links);return result;}private void dfs(int depth) {List<String> currentPoints = new ArrayList<>();for (String key : toNum.keySet()) {if (toNum.get(key) == 0) {currentPoints.add(key);addMapValue(toNum, key, -1);}}if (currentPoints.isEmpty()) {return;}maxX = depth + 1;ySize.add(currentPoints.size());Collections.sort(currentPoints, new Comparator<String>() {public int compare(String o1, String o2) {return pointWeight.get(o1) - pointWeight.get(o2);}});for (int i = 0, len = currentPoints.size(); i < len; i++) {String point = currentPoints.get(i);xPosition.put(point, depth);yPosition.put(point, i);for (Map<String, String> link : links) {if (link.get("source").equals(point)) {maxMapValue(pointWeight, link.get("target"), i + 1);addMapValue(toNum, link.get("target"), -1);}}}dfs(depth + 1);}private void addMapValue(Map<String, Integer> map, String key, Integer value) {if (map.containsKey(key)) {map.put(key, map.get(key) + value);} else {map.put(key, value);}}private void maxMapValue(Map<String, Integer> map, String key, Integer value) {if (!map.containsKey(key) || map.get(key) == 0 || map.get(key) < value) {map.put(key, value);}}
}

后端 绘制有向无环图(DAG图)相关推荐

  1. 使用R语言绘制graph:无向图(ug)和有向无环图(dag)

    首先我们需要安装R语言,参考[软件]R语言-3.6.3 安装教程一文,安装完之后我们打开编辑器. 3.5版本之后,source命令不能用了,需要使用Bioconductor的话,我们需要在consol ...

  2. java 有向无环图 树_拓扑排序-有向无环图(DAG, Directed Acyclic Graph)

    条件: 1.每个顶点出现且只出现一次. 2.若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面. 有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说. 一 ...

  3. 随机生成一个有向无环图

    写数据结构作业时想到的一个问题- 我们不妨先做一些这个随机的有向无环图的假设: 首先,它是个有向无环图,并且没有重边 假设随机从图中取出两个不相同的点,那么它们之间有边的概率为固定值(其实还可以有其他 ...

  4. java 有向无环图_数据调度系统中有向无环图的无环检测

    点击上方蓝字关注DolphinScheduler(海豚调度) |作者:鲍亮 |编辑:卢凯瑞 1 名词解释 DAG,全称:Directed Acyclic Graph,中文:有向无环图 入度:有向图中某 ...

  5. 算法精解:DAG有向无环图

    DAG是公认的下一代区块链的标志.本文从算法基础去研究分析DAG算法,以及它是如何运用到区块链中,解决了当前区块链的哪些问题. 关键字:DAG,有向无环图,算法,背包,深度优先搜索,栈,BlockCh ...

  6. C#实现有向无环图(DAG)拓扑排序

    对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在 ...

  7. 有向无环图DAG 拓扑排序 代码解释

    目录: DAG定义 举例描述 实际运用 算法描述 算法实战 算法可视化 定义 在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(英语:Topological ...

  8. IPFS系列 - 默克有向无环图(Merkle DAG)

    Merkle DAG的全称是Merkle Directed Acyclic Graph(默克有向无环图).它是在Merkle Tree的基础上构建的,Merkle Tree由美国计算机学家Merkle ...

  9. 使用R包topGO绘制GO有向无环图

    GO有向无环图 topGO 官方说明链接:http://www.bioconductor.org/packages/release/bioc/html/topGO.html 实战代码 ##R脚本 bi ...

最新文章

  1. android的xml置底_Android布局之xml设置
  2. html css integrity,integrity 属性
  3. 最佳学习方法(3)听课--听一反三
  4. java左右三角_java打印一个顺序与倒序的杨辉三角,要求两个三角左右排列
  5. metinfov5.0.4漏洞复现
  6. 【搜索引擎基础知识1】搜索引擎的技术架构
  7. java批量处理数据库语句_Java项目中调用bat批处理进行多用户数据库备份
  8. Java JVM 汇编代码入门 GitChat链接
  9. MybatisPlus 的 MetaObjectHandler 与 @TableLogic
  10. Arts 第九周(5/13 ~ 5/19)
  11. python doc转pdf
  12. AmazeUI 图标的示例代码
  13. 图片标签及以图搜图场景应用
  14. linux启动lighttpd服务,Linux下Lighttpd的安装配置
  15. c#:list转datatable;xtraReport打印
  16. 深度学习入门(三)一种预测阶段使用任意参数的滑动平均的快捷方式
  17. php 递归无限极分类和层级展示(适用于权限管理和分类管理功能)
  18. 用Python画中国地图,实现各省份数据可视化!可视化简直了!
  19. 联想服务器rd系列,联想ThinkServer RD550服务器首发评测
  20. 050_阵列天线方向图乘积原理

热门文章

  1. 几个有用的数学概念-数论
  2. 图解 TCMalloc
  3. 技术英语单词中英文对照
  4. 【SEO优化】什么是长尾关键词?
  5. ppt模板最后一页写什么?
  6. html怎么设置出场动画,CSS3 元素出现动画实例
  7. Adaptive AUTOSAR架构介绍(3)
  8. c226打印机驱动安装_打印机驱动无法安装怎么办 打印机驱动安装方法【介绍】...
  9. win7远程桌面怎么关闭计算机,win7系统远程桌面功能关闭掉的操作方法
  10. 如何删除金山毒霸的顽固的残留文件?