对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序.

线性结构概念

总的来说,“线性结构”是一个有序数据元素的集合 线性结构满足以下特点:

  1. 集合中必存在唯一“第一个元素”;
  2. 集合中必存在唯一“最后一个元素”;
  3. 除了最后一个元素,所有元素均有唯一“后继结点”;
  4. 除了第一个元素,所有元素均有唯一“前趋结点”

和我们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

C#实现有向无环图(DAG)拓扑排序的更多相关文章

  1. 算法87-----DAG有向无环图的拓扑排序

    一.题目:课程排表---210 课程表上有一些课,是必须有修学分的先后顺序的,必须要求在上完某些课的情况下才能上下一门.问是否有方案修完所有的课程?如果有的话请返回其中一个符合要求的路径,否则返回[] ...

  2. CSU 1804: 有向无环图(拓扑排序)

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在 ...

  3. 大数据工作流任务调度--有向无环图(DAG)之拓扑排序

    点击上方蓝字关注DolphinScheduler(海豚调度) |作者:代立冬 |编辑:闫利帅 回顾基础知识: 图的遍历 图的遍历是指从图中的某一个顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点 ...

  4. [笔记] 有向无环图 DAG

    最小链覆盖 (最长反链) 最小链覆盖 \(=n-\) 最大匹配. 考虑首先每个点自成一条链,此时恰好有 \(n\) 条链,最终答案一定是合并(首尾相接)若干条链形成的. 将两点匹配的含义其实就是将链合 ...

  5. 【模板整合计划】图论—有向无环图 (DAG) 与树

    [模板整合计划]图论-有向无环图 (DAG) 与树 一:[拓扑排序] 最大食物链计数 \(\text{[P4017]}\) #include<cstring> #include<cs ...

  6. 判断有向无环图(DAG)

    1.拓扑排序 bfs 所有入度为0的先入选. 2.tarjan 1个点1个集合 3.暴力 一个点不能重新到达自己

  7. pagerank算法在数学模型中的运用(有向无环图中节点排序)

    一.模型介绍 pagerank算法主要是根据网页中被链接数用来给网页进行重要性排名. 1.1模型解释 模型核心: a. 如果多个网页指向某个网页A,则网页A的排名较高. b. 如果排名高A的网页指向某 ...

  8. 题目1448:Legal or Not(有向无环图判断——拓扑排序问题)

    题目链接:http://ac.jobdu.com/problem.php?pid=1448 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...

  9. 图->有向无环图->拓扑排序

    文字描述 关于有向无环图的基础定义: 一个无环的有向图称为有向无环图,简称DAG图(directed acycline graph).DAG图是一类较有向树更一般的特殊有向图. 举个例子说明有向无环图 ...

随机推荐

  1. Android sqlite 使用框架

    Android数据库存储 前言: 今天无聊就试试水,写写博客,在之前andorid使用数据储存好像大概有5种方式,其中轻量级的是sqlite数据库,但是sqlite使用起来好像有麻烦,首先要判断…之后 ...

  2. .net如何解析二维码图片

    二维码现在越来越流行,可以使用手机上或其它移动终端上的二维码扫描器软件对着二维码一扫,就可以得到相关信息.在互联网站上,可以找到很多二维码的工具,甚至还有不少在线生成.解析二维码的网站.在业务系统当中 ...

  3. php get_magic_quotes_gpc()

    magic_quotes_gpc函数在php中的作用是判断解析用户输入的数据,如包括有:post.get.cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序异常,特别是数据库语句因为 ...

  4. django 添加自定义context

    文档参考;http://python.usyiyi.cn/django_182/ref/templates/api.html 添加自定义上下文文件custom_processors.py # codi ...

  5. ural 2023 Donald is a postman(水)

    2023. Donald is a postman Time limit: 1.0 secondMemory limit: 64 MB Donald Duck works as a postman f ...

  6. JIRA 的安装和使用

    需要的软件 6.0.3-x32.exe jira_6.x_language_zh_CN.jar jira_crack.zip http://pan.baidu.com/s/1dEbpJc1 (从网盘下 ...

  7. 使用NSUserDefaults保存自定义对象(转)

    转自http://zani.iteye.com/blog/1431239 .h文件 #import <Foundation/Foundation.h> @interface MyObjec ...

  8. python any函数

    pyhton的any() 函数: 判断给定的可迭代参数 iterable : 全部为 False,返回 False; 至少有一个为 True,则返回 True. 元素除了是 0.空.FALSE 外都算 ...

  9. uva11078 - Open Credit System(动态维护关键值)

    这道题使用暴力解法O(n*n)会超时,那么用动态维护最大值可以优化到O(n).这种思想非常实用. #include<iostream> #include<cstdio> #in ...

  10. Zeroc Ice 发布订阅者之demo Icestorm之clock

    刚刚在服务端(192.168.0.113)和客户端跑通(192.168.0.188),在这里记录,作为备忘. 第一步:读readme,先用vs2010生成subscriber.exe和publishe ...