拓扑排序用于查找相互依赖的元素的线性排序。例如,如果事件“B”依赖于事件“A”,则“A”按拓扑顺序排在“B”之前。

该模式定义了一种简单的方法来理解对一组元素执行拓扑排序的技术。

该模式的工作方式如下:

初始化

a) 使用 HashMap(或List数组)将图存储在邻接列表中;

b) 使用 HashMap 来构建邻接表, 计算所有节点的入度

c) 将所有入度为0的顶点都将作为源并存储在队列queue中。

a) 对于每个源,执行以下操作:

-i) 将其添加到排序列表中。

— ii) 从图的邻接表中获取它所有的邻接点。

— iii) 将每个孩子的入度减少 1。

— iv) 如果孩子的入度变为“0”,则将其添加到源队列中。

b) 重复(a),直到源队列为空。

具体过程请查看下图. 一个有向图包括[A, B, C, D, E]个节点和对应的边.

找到入度为0的节点B:

将B放入队列中,去掉B节点,将与B临界的节点入度减少1.

如果节点入度减少为0,将该节点放入队列中,重复上述操作:

最终得到的topological sort序列如下所示:

下面我们来看leetcode中topological sort可以解决的一类问题:

https://leetcode.com/problems/course-schedule/

这道题符合拓扑排序的要求,可以看出来课程是有先后顺序,互相依赖的.我们使用有向图可以很好的表示这种关系.那么问题可以转变成一个有向图中是否存在环的问题.如果存在环,证明存在课程之前的循环依赖,那么该课程就不能完成所有的课程.

代码如下:

public boolean canFinish(int numCourses, int[][] prerequisites) {// 使用邻接表建图List[] graph = new ArrayList[numCourses];int[] inDegree = new int[numCourses];// queue存储入度为0的节点Queue<Integer> queue = new LinkedList<>();// 给graph[i]分配空间for (int i = 0; i < numCourses; i++) {graph[i] = new ArrayList<Integer>();}// 使用邻接表建图,生成inDegree值for (int[] edge : prerequisites) {graph[edge[1]].add(edge[0]);inDegree[edge[0]]++;}// 将入度为0的节点放到queuefor (int i = 0; i < numCourses; i++) {if (inDegree[i] == 0) {queue.offer(i);}}int count = 0;  // 最终check出队列的课程数量是否等于输入的数量,等于说明每个节点都变成了入度为0的节点,表示边已经删除殆尽while(!queue.isEmpty()) {int course = queue.poll();count++;for (int i = 0; i < graph[course].size(); i++) {  // 查找它的临接节点,删除边(将它们的度减1)int neighbor = (int)graph[course].get(i);if (--inDegree[neighbor] == 0) queue.offer(neighbor); // 如果入度为0则加到queue中}}return count == numCourses;}

https://leetcode.com/problems/course-schedule-ii/

这道题和上面的一样,唯一不同的是需要将课程顺序排列出来. 而结果就是topological sort之后存储的元素. 代码如下:

public int[] findOrder(int numCourses, int[][] prerequisites) {// 使用邻接表建图List[] graph = new ArrayList[numCourses];int[] inDegree = new int[numCourses];int[] res = new int[numCourses];  // 返回的topological sorting结果int index = 0;// queue存储入度为0的节点Queue<Integer> queue = new LinkedList<>();// 给graph[i]分配空间for (int i = 0; i < numCourses; i++) {graph[i] = new ArrayList<Integer>();}// 使用邻接表建图,生成inDegree值for (int[] edge : prerequisites) {graph[edge[1]].add(edge[0]);inDegree[edge[0]]++;}// 将入度为0的节点放到queuefor (int i = 0; i < numCourses; i++) {if (inDegree[i] == 0) {queue.offer(i);res[index++] = i;}}while(!queue.isEmpty()) {int course = queue.poll();for (int i = 0; i < graph[course].size(); i++) {  // 查找它的临接节点,删除边(将它们的度减1)int neighbor = (int)graph[course].get(i);if (--inDegree[neighbor] == 0) {queue.offer(neighbor); // 如果入度为0则加到queue中res[index++] = neighbor;}}}return index == numCourses ? res : new int[0];}

https://leetcode.com/problems/course-schedule-iv/

这道题和上面两道都是课程预定,这道题就是给出一个quaries列表,需要将其中的课程依次check是否可上.那么也就是在一个有向图中,查看对应的两门课程是否有一个可达的关系.我们也可以采用拓扑排序,需要做的是需要生成一个课程i的先修课程集合j的对应关系的map, 而生成这个map可以使用topological sort算法.

具体的解释可以查看代码和注释:

public List<Boolean> checkIfPrerequisite(int numCourses, int[][] prerequisites, int[][] queries) {// 返回结果List<Boolean> res = new ArrayList<>();// prev(i,j) 表示i的先修课程是集合jMap<Integer, Set<Integer>> prev = new HashMap<>(); // 建立邻接表和入度表List[] graph = new ArrayList[numCourses];int[] inDegree = new int[numCourses];// 初始化图的邻接表和入度表for (int i = 0; i < numCourses; i++)  {graph[i] = new ArrayList<>();prev.put(i, new HashSet<>());}// 创建邻接表和入度表for (int[] edge : prerequisites) {graph[edge[0]].add(edge[1]);inDegree[edge[1]]++;}// topological sort找出prev关系map// 具体算法为先将入度为0的节点放到队列q中;// 出列一个节点,找到所有它的邻接点,邻接点为key,value为当前出队列的节点curr,注意还要把所有curr的先修课程给加上// 入度-1,将入度为0的节点放到队列中,循环操作,直到队列为空Queue<Integer> q = new LinkedList<>();for (int i = 0; i < numCourses; i++) {if (inDegree[i] == 0) q.offer(i);}while(!q.isEmpty()) {int curr = q.poll();for (int i = 0; i < graph[curr].size(); i++) {int adjecent = (int) graph[curr].get(i);prev.get(adjecent).add(curr);   // 邻接节点的先修课程为currprev.get(adjecent).addAll(prev.get(curr)); // 把curr的全部先修课程也要加上if (--inDegree[adjecent] == 0) {q.offer(adjecent);}}}// 遍历queries,找到最终的结果for (int[] query : queries) {if (prev.get(query[1]).contains(query[0]))res.add(true);else res.add(false);}return res;}

该文参考

https://hackernoon.com/14-patterns-to-ace-any-coding-interview-question-c5bb3357f6ed

专题:拓扑排序(Topological sort)模式相关推荐

  1. C语言实现拓扑排序topological sort算法(附完整源码)

    C语言实现图拓扑排序算法 node结构体,Graph结构体,Stack结构体 实现以下9个接口 完整头文件 完整源文件 完整main函数测试文件 node结构体,Graph结构体,Stack结构体 s ...

  2. 拓扑排序(topological sorting)介绍及Python实现

    目录 1. 拓扑排序 2. 拓扑排序存在的前提 3. 拓扑排序的唯一性问题 4. 拓扑排序算法原理 4.1 广度优先遍历 4.2 深度优先遍历 5. 代码实现 5.1 Graph类的实现 5.2 广度 ...

  3. 【zz】如何去理解 拓扑排序算法

    from http://www.cnblogs.com/shanyou/archive/2006/11/16/562861.html 查看Castle的代码,在Castle.Core中内部的数据结构采 ...

  4. 图综合练习--拓扑排序_03 数据结构与算法 - 排序

    1. 冒泡排序 Bubble Sort 基本思想 给定一个数组,这些元素将通过相互之间的比较,按照大小顺序一个个地像气泡一样浮出水面 实现 每一轮,从头部开始,每两个元素比较大小进行交换,直到这一轮中 ...

  5. 如何理解拓扑排序算法(转)

    对于一条有向边(u,v),定义u < v:满足所有这样条件的结点序列称为拓扑序列.拓扑排序就是求一个有向图的拓扑序列的算法. 一个有向图顶点的拓扑序列不是惟一的.并不是任何有向图的顶点都可以排成 ...

  6. 算法高级(33)-拓扑排序-maven依赖关系的确定

    一.拓扑排序(Topological Sorting) 1.定义 拓扑排序是一种图论算法,该算法在<数据结构与算法>一书中有涉猎.引用维基百科的定义:在图论中,由一个有向无环图的顶点组成的 ...

  7. 拓扑排序(topo_sort)

    拓扑排序 预备知识 ​   一个较大的工程往往被划分成许多子工程,我们把这些子工程称作活动(activity).在整个工程中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,也就是说,一个子工 ...

  8. 图的拓扑排序(AOV网络)

    文章目录 拓扑排序 概念 实现 邻接表(队列) 邻接矩阵(栈) 总结 源代码 邻接表 邻接矩阵 拓扑排序 概念 拓扑排序是对有向无环图的顶点的一种排序. AOV网络 : 在有向图中, 用顶点表示活动或 ...

  9. 关键路径 详解 (前置知识:拓扑排序)

    图论之关键路径讲解 回顾所需知识: 拓扑排序 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若 ...

最新文章

  1. cocurrent包semaphore信号量
  2. 【Tools】MarkDown教程(五)-CSDN MarkDown介绍
  3. Valgrind ---内存调试,内存泄漏检测以及性能分析的软件开发工具
  4. docker run 挂载卷_docker mysql配置挂载到卷
  5. 99 网络编程_网络工程师技能图谱,看看你会多少技能
  6. 可怕的北京大学出版社--javascript也叫java
  7. 微信小程序获取unionid与openid
  8. phpcms 调用多级栏目和多级栏目下的文章列表
  9. WPA3 标准被曝严重漏洞,WiFi 密码可遭窃取?
  10. 郭天祥《新概念51单片机C语言教程》序言
  11. kindle刷机ttl_“免费” PHICOMM 斐讯 K2路由器TTL刷机全纪录
  12. 数字化营销如何打造全链路数据统计解决方案
  13. 两个PNP三极管组成限流电路原理分析
  14. CSR1010A05-IQQM-R首款单模单芯片蓝牙低功耗
  15. 2021年全国程序员工资出炉想要年薪60万,难吗?网友,扎心了
  16. Matplotlib系列(三):坐标轴变换及注释
  17. 细胞穿膜肽-MnO2复合物(TAT-MnO2)多肽偶联氧化锰纳米粒|MnO2包裹聚多巴胺的纳米颗粒
  18. MOSS的备份与还原
  19. PAT乙级 ——开学寄语
  20. 神级软件—uTinyRipper

热门文章

  1. 其他品牌的触控笔能用在ipad上?性价比高的触控笔合集
  2. 使用latex做IEEE ACCESS排版时候,解决模板作者信息之间的距离问题。
  3. attention 文字识别算法_支持40种语言的图片文字识别(OCR)项目
  4. Python Turtle 绘制蝴蝶曲线
  5. 打开 Office 出现配置进度然后报错“Microsoft Office 无法找到此应用程序的许可证,修复尝试失败或者已被取消”
  6. c#中如何用codesoft来打印标签开发分享
  7. FFmpeg滤镜:制作图片视频流(续)
  8. C语言中sort函数的用处
  9. 【RFC5382 TCP 的 NAT 行为要求】(翻译)
  10. Win7下调出任务快捷栏