对一个有向无环图(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 MySort(IEnumerable source, Func> getDepends)
{
// 访问过的路径
Dictionary visited = new Dictionary();
// 已经排过序的
List sorted = new List();
foreach (var item in source)
{
Visit(item, getDepends, visited, sorted);
}
return sorted;
}
static void Visit(T item, Func> getDepends, Dictionary visited, List 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);
}
}
算法87-----DAG有向无环图的拓扑排序
一.题目:课程排表---210 课程表上有一些课,是必须有修学分的先后顺序的,必须要求在上完某些课的情况下才能上下一门.问是否有方案修完所有的课程?如果有的话请返回其中一个符合要求的路径,否则返回[] ...
CSU 1804: 有向无环图(拓扑排序)
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在 ...
【模板整合计划】图论—有向无环图 (DAG) 与树
[模板整合计划]图论-有向无环图 (DAG) 与树 一:[拓扑排序] 最大食物链计数 \(\text{[P4017]}\) #include #include
判断有向无环图(DAG)
1.拓扑排序 bfs 所有入度为0的先入选. 2.tarjan 1个点1个集合 3.暴力 一个点不能重新到达自己
pagerank算法在数学模型中的运用(有向无环图中节点排序)
一.模型介绍 pagerank算法主要是根据网页中被链接数用来给网页进行重要性排名. 1.1模型解释 模型核心: a. 如果多个网页指向某个网页A,则网页A的排名较高. b. 如果排名高A的网页指向某 ...
题目1448:Legal or Not(有向无环图判断——拓扑排序问题)
题目链接:http://ac.jobdu.com/problem.php?pid=1448 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
图->;有向无环图->;拓扑排序
文字描述 关于有向无环图的基础定义: 一个无环的有向图称为有向无环图,简称DAG图(directed acycline graph).DAG图是一类较有向树更一般的特殊有向图. 举个例子说明有向无环图 ...
【拓扑】【宽搜】CSU 1084 有向无环图 (2016湖南省第十二届大学生计算机程序设计竞赛)
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1804 题目大意: 一个有向无环图(DAG),有N个点M条有向边(N,M<=105 ...
JavaScript + SVG实现Web前端WorkFlow工作流DAG有向无环图
一.效果图展示及说明 (图一) (图二) 附注说明: 1. 图例都是DAG有向无环图的展现效果.两张图的区别为第二张图包含了多个分段关系.放置展示图片效果主要是为了说明该例子支持多段关系的展现(当前也 ...
随机推荐
如何远程断点调试本地localhost项目
前言 对于一般开发网站的IDE自带的服务器是都跑在 localhost 地址上的.(如下图的asp.net) 而这种地址是只能在本机通过 localhost 或 127.0.0.1 地址访问到,而无法 ...
css3 的content 属性
content属性想必大家都熟悉了,一般结合伪类一起使用,表示显示的内容 例如:.box:before{content:"hello";width:100px;line-heigh ...
C++const与指针
1.指向常量的指针变量 指向常量的指针变量的定义方法: const 类型标识符 *指针变量名: 如: const int *p; 这种方法定义的指针变量只可读取它所指向的变量或常量的值,不可借助该指 ...
.net项目IIS、VS 附加进程调试
IIS调试 1.首先要把项目发布至IIS上,确保项目能正常运行. 2.从IIS上右键站点>管理网站>浏览 或者打开“内容视图“ 选择一个文件右键>浏览. 3.用vs打开该项目,选择 ...
Tar打包、压缩与解压缩到指定目录的方法
tar在linux上是常用的打包.压缩.加压缩工具,他的参数很多,折里仅仅列举常用的压缩与解压缩参数 参数: -c :create 建立压缩档案的参数: -x : 解压缩压缩档案的参数: -z : 是 ...
MSSQL - 备份和还原数据库
SQL语句备份和还原数据库:http://blog.csdn.net/liuhelong/article/details/3335687 1.MSSQL - SqlServer:此数据库处于单用户模式 ...
为ASP.NetCore程序启用SSL
紧接着上一篇搭建连接MySql的三层架构的ASP.NetCore2.0的WebApi的案例,这篇来实现为ASP.NetCore启用SSL支持 由于ASP.NetCore默认服务器Kestrel不像ii ...
sqlserver 重置标识列
重置标识信息:DBCC CHECKIDENT('表名', RESEED,0) 检查标识信息:DBCC CHECKIDENT('SysModule', NORESEED)
bzoj 1407: [Noi2002]Savage
Description 解题报告: 因为给定答案范围,暴力枚举时间,然后再两两枚举野人,判断是否有可能在某一年相遇,我们设这一年为\(x\),那么显然相交的条件是: \(x*(p[i]-p[j])+y ...
python学习Day9 内存管理
复习 :文件处理 1. 操作文件的三步骤:-- 打开文件:此时该文件在硬盘的空间被操作系统持有 | 文件对象被应用程序持用 -- 操作文件:读写操作 -- 释放文件:释放操作系统对文件在硬盘间的持有 ...