简单易懂的拓扑排序

1.定义算法

对一个有向无环图(Directed Acyclic Graph简称DAG) G进行拓扑排序,是将G中全部顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出如今v以前。一般,这样的线性序列称为知足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序获得该集合上的一个全序,这个操做称之为拓扑排序。学习

在AOV网中,若不存在回路,则全部活动可排列成一个线性序列,使得每一个活动的全部前驱活动都排在该活动的前面,咱们把此序列叫作拓扑序列(Topological order),由AOV网构造拓扑序列的过程叫作拓扑排序(Topological sort)。AOV网的拓扑序列不是惟一的,知足上述定义的任一线性序列都称做它的拓扑序列。 ui

2.拓扑排序的实现步骤spa

在有向图中选一个没有前驱的顶点而且输出。3d

从图中删除该顶点和全部以它为尾的弧(白话就是:删除全部和它有关的边)。code

重复上述两步,直至全部顶点输出,或者当前图中不存在无前驱的顶点为止,后者表明咱们的有向图是有环的,所以,也能够经过拓扑排序来判断一个图是否有环。blog

3.拓扑排序实例手动实现排序

若是咱们有以下的一个有向无环图,咱们须要对这个图的顶点进行拓扑排序,过程以下:队列

 

首先,咱们发现V6和v1是没有前驱的,因此咱们就随机选去一个输出,咱们先输出V6,删除和V6有关的边,获得以下图结果:it

 

而后,咱们继续寻找没有前驱的顶点,发现V1没有前驱,因此输出V1,删除和V1有关的边,获得下图的结果:

 

而后,咱们又发现V4和V3都是没有前驱的,那么咱们就随机选取一个顶点输出(具体看你实现的算法和图存储结构),咱们输出V4,获得以下图结果:

 

而后,咱们输出没有前驱的顶点V3,获得以下结果:

 

而后,咱们分别输出V5和V2,最后所有顶点输出完成,该图的一个拓扑序列为:

v6–>v1—->v4—>v3—>v5—>v2

过程简述:

从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。

从图中删除该顶点和全部以它为起点的有向边。

重复 1 和 2 直到当前的 DAG 图为空或当前图中不存在无前驱的顶点为止。若当前图中不存在无前驱的顶点说明有向图中必存在环。

4.拓扑排序Java实现

(1)   示例

如今你总共有 n 门课须要选,记为 0 到 n-1。

在选修某些课程以前须要一些先修课程。 例如,想要学习课程 0 ,你须要先完成课程 1 ,咱们用一个匹配来表示他们: [0,1]

给定课程总量以及它们的先决条件,判断是否可能完成全部课程的学习?

示例 1:

输入: 2, [[1,0]]

输出: true

解释: 总共有 2 门课程。学习课程 1 以前,你须要完成课程 0。因此这是可能的。

示例 2:

输入: 2, [[1,0],[0,1]]

输出: false

解释: 总共有 2 门课程。学习课程 1 以前,你须要先完成​课程 0;而且学习课程 0 以前,你还应先完成课程 1。这是不可能的。

说明:

输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法。

你能够假定输入的先决条件中没有重复的边。

(2)   截图步骤:

本题思路:采用拓扑排序+广度优先搜索的方式进行求解。

步骤一:对全部节点创建一个入度表times,times[i]表示第i个节点有多少个入度,(这里入度的意思是当实现此节点时,须要多少个前驱节点的支持)。

步骤二:将入度表中入度为0的节点添加到队列que中。

步骤三:取出队列第一个元素temp;并将times中,以该节点做为前驱节点的入度减一,并判断入度是否等于0,若是等于0加入到队列中。

步骤四:重复步骤三,知道队列为空,判断times中是否存在非0的节点,若是存在则说明有环,不存在说明无环。(其中队列每次输出的值就是拓排序的输出值)

(3)   Java代码:

class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { int []times=new int[numCourses]; for(int i=0;i<prerequisites.length;i++) { int num=prerequisites[i][0]; times[num]=times[num]+1; } Queue<Integer> que=new LinkedList<Integer>(); for(int j=0;j<times.length;j++) { if(times[j]==0) { que.add(j); } } while(!que.isEmpty()) { int temp=que.poll(); for(int m=0;m<prerequisites.length;m++) { if(prerequisites[m][1]==temp) { times[prerequisites[m][0]]--; if(times[prerequisites[m][0]]==0) { que.add(prerequisites[m][0]); } } } } for(int e=0;e<times.length;e++) { if(times[e]!=0) { return false; } } return true; } }
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息