C#实现有向无环图(DAG)拓扑排序
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序.
线性结构概念
总的来说,“线性结构”是一个有序数据元素的集合 线性结构满足以下特点:
- 集合中必存在唯一“第一个元素”;
- 集合中必存在唯一“最后一个元素”;
- 除了最后一个元素,所有元素均有唯一“后继结点”;
- 除了第一个元素,所有元素均有唯一“前趋结点”
和我们abp Module很像,第一个加载模块永远是其ABP核心模块,最后一个模块永远是我们的启动模块
举例
1.大学课程排序
大学课程的学习是有先后顺序的,C语言是基础,数据结构依赖于C语言,其它课程也有类似依赖关系。这样的一个课程安排是怎么实现的呢?
2.VS项目编译顺序
假设VS中有三个项目A,B,C,它们的关系如下。VS编译器是如何判断三个项目的编译顺序的呢?
A->B->C A引用B B引用C
A->B->C->A 提示循环引用
ABP的Module
ABP中的模块也是如此,不可循环引用相互依赖A->B B->A
X
前面说到ABP中的第一个模块和最后一个模块是确定的。
呢么中间的是怎么排序的呢。其实用的是拓扑算法
从图中可以得知:
1.A模块是最核心的,不依赖于其他任何模块
2.D依赖E和B,E依赖B和C,B依赖C和A,C依赖A
那么根据拓扑排序,应该如何排序呢?
1.从图中找一个没有前驱指向它的顶点
2.删除该顶点.以及该顶点的前驱
3.重复步骤 1 and 2 ,直到图中顶点为空 或者 找不到步骤1中这样的顶点 为止.
排序如下:
结果就是D->E->B->C->A
排完之后正好对应D依赖E和B,E依赖B和C,B依赖C和A,C依赖A
这个顺序在ABP的模块这看来是行不通的,需要在反转一次,最先加载A,才行。
C#实现深度优先搜索
有这样一个DAG图
如果对它进行排序的话,其实过程是这样的.
图中,顶点A是没有指向它的前驱的,所以从它开始访问
1.访问 A
2.访问 B
3.访问 C
在访问了 B 后应该是访问 B 的另外一个顶点,这里可以是随机的也可以是有序的,具体取决于你存储的序列顺序,这里先访问 C 。
4.访问 E
5.访问 D
这里访问 D 是因为 B 已经被访问过了,所以访问顶点 D 。
6.访问 F
因为顶点 C 已经被访问过,所以应该回溯访问顶点 B 的另一个有向边指向的顶点 F 。
7.访问 G
那么代码应该如何写呢?
source:需要排序的集合
getDepends:一个func委托,用于获取当前模块依赖的其他模块
方法内部维护了一个字典对象Visited 用于存储已经访问过的模块,key表示模块,value是一个bool,true时表示正在处理,false表示以及处理完成,
处理完成的模块会加入到sorted集合中
static List<T> MySort<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getDepends)
{// 访问过的路径Dictionary<T, bool> visited = new Dictionary<T, bool>();// 已经排过序的List<T> sorted = new List<T>();foreach (var item in source){Visit<T>(item, getDepends, visited, sorted);}return sorted;
}static void Visit<T>(T item, Func<T, IEnumerable<T>> getDepends, Dictionary<T, bool> visited, List<T> sorted)
{//已经访问过了if (visited.ContainsKey(item)){bool isVisit = visited[item];if (isVisit == true){throw new Exception("循环引用");}}//未访问else{visited.Add(item, true);//true :正在访问 false:访问完成//获取所有依赖var depends = getDepends(item);foreach (var depend in depends){Visit(depend, getDepends, visited, sorted);}//访问完成visited[item] = false;sorted.Add(item);}}
完整demo github
转载于:https://www.cnblogs.com/zzqvq/p/10260397.html
C#实现有向无环图(DAG)拓扑排序相关推荐
- 有向无环图DAG 拓扑排序 代码解释
目录: DAG定义 举例描述 实际运用 算法描述 算法实战 算法可视化 定义 在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(英语:Topological ...
- 有向无环图(DAG)拓扑排序的两种方法
如下图的DAG: 第一种: (1)从AOV网中选择一个没有前驱的顶点并且输出它: (2)从AOV网中删除该顶点,并且上去所有该顶点为尾的弧: (3)重复上述两步,直到全部顶点都被输出,或者AOV网中不 ...
- 【图论】有向无环图的拓扑排序
1. 引言 有向无环图(Directed Acyclic Graph, DAG)是有向图的一种,字面意思的理解就是图中没有环.常常被用来表示事件之间的驱动依赖关系,管理任务之间的调度.拓扑排序是对DA ...
- 数据结构-考研难点代码突破 (C++实现有向无环图的拓扑排序)
文章目录 1. AOV网 2. 拓扑排序 C++代码 1. AOV网 AOV网∶若用DAG 图(有向无环图)表示一个工程,其顶点表示活动,用有向边<Vi,Vj>表示活动 Vi必须先于活动V ...
- 判定有向无环图 (拓扑排序)
问题描述: 给出一张有向图,问它是否存在环. 解题思路: 这里可以用到拓扑排序. 拓扑排序的定义 拓扑排序应用于有向无环图之中,排序完以后会出现这样的性质:对于一个点p,只对排序位置在它之后的点有边. ...
- 带你了解有向无环图和拓扑排序
写在前面 如果觉得有所收获,记得点个关注和点个赞,感谢支持. 今天遇到有向无环图的一些问题,感觉挺有意思的,而且这些问题的思路特点都差不多,所以想着记录一下.在图论中,如果一个有向图无法从某个顶点出发 ...
- 有向无环图的拓扑排序
拓扑排序 对于一个有向无环图,我们可以这样确定一个图中顶点的顺序: 对于所有的u.v,若存在有向路径u-->v,则在最后的顶点排序中u就位于v之前.这样确定的顺序就是一个图的拓扑排序. ...
- 有向无环图的拓扑排序 关键路径
拓扑排序:在不违背先决条件的基础上将有向无环图排成线性序列 - 排序结果不唯一 - 用一维数组Indegree存储各顶点的入度 - 采用邻接表与队列 bool TopSort(LGraph Graph ...
- 后端 绘制有向无环图(DAG图)
因为公司的某个系统比较古老,里面的 job 的管理几乎都是直接通过操作数据库来实现的,对于一般的操作还可以忍受,但是每次想知道 job 之间的依赖关系的时候,就会相当难受,于是便脑袋很抽地一定要写一个 ...
最新文章
- mysql平均锁_MySQL锁情况分析
- 饶毅:脑、物理、化学、 生物、心理认知的交叉研究
- hdu2594 简单KMP
- 阿里巴巴拿下奥运顶级赞助商
- ES6新特性之解构表达式
- C语言家谱管理程序,课内资源 - 基于C语言实现的家谱管理系统
- 依据地图上的经纬度坐标计算某个点到多边形各边的距离
- 哈工大大数据实验_科研常用 | 实验大数据分析方法
- JVM中的五大内存区域划分详解
- java 注解入门 简书_Java基础-注解
- 77-CCI,Commodity Channel Index,商品通道指标.(2015.7.1)
- SSM框架Web程序的流程(Spring SpringMVC Mybatis)
- STL之容器——介绍
- CKEditor富文本编辑器使用
- IE 7打开网页慢解决方法
- 关于门控时钟的毛刺解决
- 输入年月日实现计算这是一年的第几天
- 全球与中国连续光纤激光器市场现状及未来发展趋势
- 用python画带有正负值的条形图
- 商务呈现之客户满意度