业务上有一个需求是检测工作流模板是否是DAG图,DAG图即有向无环图,常见的解决方法是拓扑排序,如果存在环路,则不能进行拓扑排序。
拓扑排序
拓扑排序是有向无环图所有顶点的线性序列。
满足两个条件:
- 每个顶点只出现一次
- 若存在从A到B的路径,那么序列中A出现在B之前
环路检测算法
- 找到入度为0的点,输出该点
- 删除该点及该点的所有出边
- 重复步骤一二,直到输出图中所有节点,如果图中有节点未输出,则存在环路
实现
例如下图存在环路
1. 确定数据格式
|
|
2.创建邻接表存储图的信息
|
|
|
|
3.找到入度为0的点,删除所有出边
|
|
删除start之后的 graph 与 node
|
|
graph中,key代表线的出点,value代表线的入点,将value去重后,与nodeSet 取差集就得到下一批入度为0的节点。
|
|
|
|
4.判断栈内节点数,若小于原始节点数则存在环路
|
|
实践中用到的Set和Map实例方法
Set
类似数组,但是成员的值唯一。
- delete(value) 删除某个值,返回布尔值,表示是否删除成功
- has(value) 返回布尔值,表示参数是否为成员
数组去重
[...new Set(array)]
并集
new Set([...a, ...b])
交集
new Set([...a].filter(x => b.has(x)))
差集
new Set([...a].filter(x => !b.has(x)))
Map
类似对象,也是键值对的集合。但是"键"不限于字符串,各种类型都可以做为键。
- set(key, value) 设置key对应的键值
- get(key) 读取key对应的键值
- has(key) 返回布尔值,表示某个键是否再Map数据结构中
- delete(key) 删除某个键
Map的遍历方法
- values() 返回键值的遍历器