概述

当我们把设计稿和技术选型定下来之后,接下来就要开始着手画这个依赖图了。依赖图的组成最简单的就是节点Node 和节点之间的连线。这一节我们要处理的就是节点位置信息的处理。为了确定节点的位置信息,首先要给节点分层,分层的信息取决于节点之间的依赖关系。

问题分析

当前我们默认图是从上到下布局方式,节点分层,最容易想到的就是拓扑排序,通过BFS 宽度优先遍历,计算每个节点的步长。

自顶向下BFS

如上图,我们如果是普通的BFS,我们会发现D 节点应该是第二层,实际上D应该是第三层,所以,实际上每个节点应该取最大的步长,实现如下

function calcLayer(nodes){var queue = [];var maxLayer = 1;var nodesT =  nodes;//  入度为0 的点放入队列for (var i = 0; i < nodesT.length; i++) {if (nodesT[i].inputNode.length === 0) {nodesT[i].layer = 1;queue.push(nodesT[i]);}}while(queue.length > 0){var tNode = queue.shift();if (tNode.outputNode && tNode.outputNode.length > 0) {for (var j = 0; j < tNode.outputNode.length; j++) {var outputNodeIndex = getNodeIndex(tNode.outputNode[j], nodesT);if(outputNodeIndex < 0) continue;if (nodesT[outputNodeIndex].layer === -1) {nodesT[outputNodeIndex].layer = tNode.layer + 1;}else{nodesT[outputNodeIndex].layer = Math.max(nodesT[outputNodeIndex].layer,tNode.layer + 1);}// 更新节点层次,选择最大值maxLayer = Math.max(maxLayer, nodesT[outputNodeIndex].layer);queue.push(nodesT[outputNodeIndex]);}}}
}

至此分层基本完成,但是发现另外一种情况,如下:

如果是按照刚才那种分发,入度为0 的节点必然在第一层,其实这种,我们可能更希望 G在第三层,F 在第二层,例如下图展示的

这样展示,图会更紧凑一点,观察图可知,在链路中间的节点,它的层级就是固定的,例如D节点,但是一些没有上游节点的,例如G,F 的位置确实可以多种选择的。在观察,我们可以知道,如果从E往上BFS,我们会发现,G,F节点就是我们需要的层次了,所以,这时候,我们需要自底向上再进行一次BFS,得到新的层级,并且用自底向上的结果去矫正自上而下的结果,这一点很关键。

自底向上BFS

function bottomToTop (nodes){var queue = [];var maxLayer = 1;for (var i = 0; i <nodes.length; i++) {if (nodes.outputNode.length === 0) {nodes[i].layer = 1;queue.push(nodes[i]);}}while(queue.length > 0){var tNode = queue.shift();if (tNode.inputNode && tNode.inputNode.length > 0) {for (var j = 0; j < tNode.inputNode.length; j++) {var inputNodeIndex = getNodeIndex(tNode.inputNode[j], nodes);if(inputNodeIndex < 0) continue;if (nodes[inputNodeIndex].layer === -1) {nodes[inputNodeIndex].layer = tNode.layer + 1;}else{nodes[inputNodeIndex].layer = Math.max(nodes[inputNodeIndex].layer,tNode.layer + 1);}maxLayer = Math.max(maxLayer, nodes[inputNodeIndex].layer);queue.push(nodes[inputNodeIndex]);}}}// 计数从下到上的,这里要转换成从上到下for(var i = 0; i < nodes.length; i++){nodes[i].layer = maxLayer + 1 - nodes[i].layer;}}

修正结果集

function fixLayer (nodesT, nodes){for(var i = 0; i < nodesT.length; i++){if(nodesT[i].inputNode.length === 0){var minL = maxLayer;var minT = maxLayer;if(nodesT[i].outputNode && nodesT[i].outputNode.length > 0){for(var j = 0; j < nodesT[i].outputNode.length; j++){var inputNodeIndex = getNodeIndex(nodesT[i].outputNode[j], nodes);var inputNodeIndexT = getNodeIndex(nodesT[i].outputNode[j], nodesT);if(inputNodeIndex < 0) continue;if(inputNodeIndexT < 0) continue;//  注意,矫正的结果不能该节点比它子节点的层级还要高,这里要和它子节点做一次比较minL = Math.min(minL, nodes[inputNodeIndex].layer - 1);minT = Math.min(minT, nodesT[inputNodeIndexT].layer - 1);}}nodesT[i].layer = Math.min(minL,minT);}}}

总结

这里主要用到了BFS,如果很熟悉这个算法的话,还是很简单的,同时要观察一些实际情况,做一些优化即可!

本文由华为云发布。

从零开始画自己的DAG作业依赖图(二)--分层布局算法相关推荐

  1. 从零开始画自己的DAG作业依赖图(三)--节点连线简单版

    概述 分层布局弄好之后,每一层的节点上下的相对位置基本确定了,我们最简单的方式,就是每一层平铺所有节点,节点宽度固定以及间距固定,每个节点的位置基本就确定了.我们只要基于这些节点进行连线就可以了. 方 ...

  2. 从零开始画自己的DAG作业依赖图(四)--节点连线优化版

    概述 上个版本简单的连线在一些复杂场景,尤其层级比较多,连线跨层级比较多的情况下,会出现线条会穿过矩形的情况,这一讲就是在这个基础上,去优化这个连线. 场景分析 在下面几种情况下,简单版本的画法已经没 ...

  3. 深蓝学院《从零开始手写VIO》作业一

    深蓝学院<从零开始手写VIO>作业一 深蓝学院<从零开始手写VIO>作业一 1. VIO文献阅读 1.1 视觉与IMU进行融合之后有何优势? 1.2 有哪些常见的视觉+IMU融 ...

  4. opencv画火车沿轨道运行-课程作业

    opencv画火车沿轨道运行-课程作业 四个函数,一个循环 一. 轨道函数 二.定义可转弯小车的方法 三.定义角度函数 四.定义约束项 五.一个循环 以下附上总代码 以下效果图 写本次博客的目的主要是 ...

  5. 从零开始用 Flask 搭建一个网站(二)

    从零开始用 Flask 搭建一个网站(一) 介绍了如何搭建 Python 环境,以及 Flask 应用基本项目结构.我们要搭建的网站是管理第三方集成的控制台,类似于 Slack. 本篇主要讲解数据如何 ...

  6. 深蓝学院《从零开始手写VIO》作业七

    深蓝学院<从零开始手写VIO>作业七 深蓝学院<从零开始手写VIO>作业七 深蓝学院<从零开始手写VIO>作业七 将第二讲中的仿真数据(视觉特征,imu数据)接入V ...

  7. 深蓝学院《从零开始手写VIO》作业六

    深蓝学院<从零开始手写VIO>作业五 深蓝学院<从零开始手写VIO>作业六 1. 证明题 2. 代码题 深蓝学院<从零开始手写VIO>作业六 1. 证明题 证明Dy ...

  8. 深蓝学院《从零开始手写VIO》作业五

    深蓝学院<从零开始手写VIO>作业五 1. 完成Bundle Adjustment求解器 2. 完成测试函数 3. 论文总结 1. 完成Bundle Adjustment求解器 完成单目 ...

  9. 深蓝学院《从零开始手写VIO》作业四

    深蓝学院<从零开始手写VIO>作业四 深蓝学院<从零开始手写VIO>作业四 1. 信息矩阵分析 2. Bundle Adjustment信息矩阵的计算 深蓝学院<从零开始 ...

最新文章

  1. helm部署postgresql
  2. myeclipse打开jsp页面慢或者卡死
  3. MMIX机器简要介绍
  4. 数组静态初始化【应用】
  5. Doris SQL执行计划
  6. 什么是计算机数字代码,计算机代码1—10这10个数字表示什么意思 例如:数字1 计算机代码00001 这是什么意思...
  7. Hyperscan 5.1.0 安装
  8. 布莱克斯科尔斯模型(三)热传导方程的解析解
  9. MacOS任意降级(完美教程)
  10. http url转义字符,特殊字符
  11. 微信小程序滚动Tab选项卡:左右滑动切换、触底加载分页
  12. 分数阶傅里叶变换Transformer
  13. # 0003:fill的游戏
  14. 【存储器了解 RAM flash和eeprom存储器的区别和作用】
  15. 易语言到字节集c,易语言字节集到十六进制文本转换方式 - 小R网络
  16. 2020最新互联网大厂职级和薪资对比,美团老人被新人严重倒挂!
  17. 做好URL路径优化,帮你快速实现网站排名
  18. 这3种扣工资行为,是违法的
  19. APP内拉起微信支付的解决方案
  20. 网站优化关键词怎么优化的(如何使搜索引擎的搜索结果优化)

热门文章

  1. 用python实现线性回归算法
  2. 函数依赖集闭包、属性集闭包、超键、候选键和最小函数依赖集的求法。
  3. 【SharePoint】通过Microsoft Graph Rest Api操作SharePoint时如何获取SharePoint站点的WebID, SiteID and ListID
  4. mysql 钩子函数_pod 生命周期hook钩子函数
  5. office工具栏不见_如何在Office中的快速访问工具栏中添加宏
  6. Hololens 2拍摄视频并同步记录眼镜参数的C#脚本
  7. python3抓取数据_python3抓取到的拉勾数据统计
  8. Vue动态粒子特效插件(背景线条吸附动画)
  9. Qt + halcon混合编程 相机标定
  10. 用awrsqrpt生成SQL执行计划