2018-05-02 16:26:07

一、拓扑排序

有向无环图(Directed acyclic graph,DAG)必定存在拓扑排序;非DAG没有拓扑排序一说。

二、拓扑排序算法

通常拓扑排序算法可以在O(n)的时间复杂度完成,具体来说是O(V + E)。

下面以leetcode207为例来介绍拓扑排序算法。

问题描述:

问题求解:

方法一、BFS

使用BFS求解拓扑排序是非常直观和简单的。

维护每个节点的indegree数目,对于入度为0的进队列,将所有入度为0的出队,并更新它们的邻接节点的indegree,若indegree == 0,入队。

循环以上操作直到队列为空。

    public boolean canFinish(int numCourses, int[][] prerequisites) {
List<Integer>[] graph = new List[numCourses];
int[] indegree = new int[numCourses];
for (int i = 0; i < numCourses; i++) graph[i] = new ArrayList<>();
for (int[] edge : prerequisites) {
int from = edge[1];
int to = edge[0];
graph[from].add(to);
indegree[to] += 1;
}
int cnt = 0;
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (indegree[i] == 0) q.add(i);
}
while (!q.isEmpty()) {
int curr = q.poll();
cnt += 1;
for (int next : graph[curr]) {
indegree[next] -= 1;
if (indegree[next] == 0) q.add(next);
}
}
return cnt == numCourses;
}

  

方法二、DFS

使用DFS代码更为简洁。

实际就是给每个节点打上状态标签,如果访问到了正在访问的节点,那么必定存在环。

另外,我们需要一个访问完成的标签,避免重复访问已经访问过的节点。

    public boolean canFinish(int n, int[][] edges) {
List<Integer>[] graph = new List[n];
for (int i = 0; i < n; i++) graph[i] = new ArrayList<>();
for (int[] e : edges) {
int from = e[1];
int to = e[0];
graph[from].add(to);
}
int[] state = new int[n];
for (int i = 0; i < n; i++) {
if (state[i] == 0 && !dfs(graph, i, state)) return false;
}
return true;
} private boolean dfs(List<Integer>[] graph, int node, int[] state) {
state[node] = 1;
for (int next : graph[node]) {
if (state[next] == 2) continue;
if (state[next] == 1) return false;
if (!dfs(graph, next, state)) return false;
}
state[node] = 2;
return true;
}

三、拓扑排序应用

  • 210. Course Schedule II

问题描述:

问题求解:

也是一条裸的拓扑排序题,相较于上一题,本题可以说是更纯粹的拓扑排序,因为不仅需要判环,还需要输出一个合法的解。当然,算法实现上也是两种思路,一是DFS,而是kahn算法。

DFS:

    public int[] findOrder(int numCourses, int[][] prerequisites) {
int[] res = new int[numCourses];
List<Integer>[] graph = new List[numCourses];
for (int i = 0; i < numCourses; i++) graph[i] = new ArrayList<>();
for (int[] pair : prerequisites) {
graph[pair[1]].add(pair[0]);
}
int[] state = new int[numCourses];
Stack<Integer> s = new Stack<>();
for (int i = 0; i < numCourses; i++) {
if (state[i] == 0)
if (!dfs(graph, state, s, i)) return new int[0];
}
for (int i = 0; i < numCourses; i++) res[i] = s.pop();
return res;
} private boolean dfs(List<Integer>[] g, int[] state, Stack<Integer> s, int i) {
if (state[i] == 2) return true;
if (state[i] == 1) return false;
state[i] = 1;
for (int node : g[i]) {
if (!dfs(g, state, s, node)) return false;
}
state[i] = 2;
s.push(i);
return true;
}

Kahn:

    public int[] findOrder(int numCourses, int[][] prerequisites) {
int[] res = new int[numCourses];
int[] indegree = new int[numCourses];
List<Integer>[] graph = new List[numCourses];
for (int i = 0; i < numCourses; i++) graph[i] = new ArrayList<>();
for (int[] pair : prerequisites) {
graph[pair[1]].add(pair[0]);
indegree[pair[0]]++;
}
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (indegree[i] == 0)
q.add(i);
}
int cnt = 0;
while (!q.isEmpty()) {
int p = q.poll();
res[cnt++] = p;
for (int node : graph[p]) {
if (--indegree[node] == 0) q.add(node);
}
}
if (cnt == numCourses) return res;
else return new int[0];
}
  • 1203. Sort Items by Groups Respecting Dependencies

问题描述

问题求解

    public int[] sortItems(int n, int m, int[] group, List<List<Integer>> beforeItems) {
Map<Integer, Set<Integer>> group2items = new HashMap<>();
Map<Integer, Set<Integer>> group_g = new HashMap<>();
Map<Integer, Integer> g_indegree = new HashMap<>();
Map<Integer, Set<Integer>> item_g = new HashMap<>();
Map<Integer, Integer> i_indegree = new HashMap<>(); int num_of_groups = m; for (int i = 0; i < group.length; i++) {
if (group[i] == -1) group[i] = num_of_groups++;
} for (int i = 0; i < num_of_groups; i++) {
group2items.put(i, new HashSet<>());
group_g.put(i, new HashSet<>());
g_indegree.put(i, 0);
} for (int i = 0; i < n; i++) {
item_g.put(i, new HashSet<>());
i_indegree.put(i, 0);
group2items.get(group[i]).add(i);
} for (int to = 0; to < beforeItems.size(); to++) {
int to_group = group[to];
for (int from : beforeItems.get(to)) {
int from_group = group[from];
if (to_group == from_group) {
item_g.get(from).add(to);
i_indegree.put(to, i_indegree.get(to) + 1);
}
else {
if (!group_g.get(from_group).contains(to_group)) {
group_g.get(from_group).add(to_group);
g_indegree.put(to_group, g_indegree.get(to_group) + 1);
}
}
}
} // check groups
List<Integer> groups = new ArrayList<>();
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < num_of_groups; i++) {
if (g_indegree.get(i) == 0) {
q.add(i);
groups.add(i);
}
}
while (!q.isEmpty()) {
int cur = q.poll();
for (int to : group_g.get(cur)) {
g_indegree.put(to, g_indegree.get(to) - 1);
if (g_indegree.get(to) == 0) {
q.add(to);
groups.add(to);
}
}
}
if (groups.size() != num_of_groups) return new int[0]; // check items
List<Integer> res = new ArrayList<>();
for (int g : groups) {
int num = 0;
q = new LinkedList<>();
for (int item : group2items.get(g)) {
if (i_indegree.get(item) == 0) {
q.add(item);
res.add(item);
num += 1;
}
} while (!q.isEmpty()) {
int cur = q.poll();
for (int to : item_g.get(cur)) {
i_indegree.put(to, i_indegree.get(to) - 1);
if (i_indegree.get(to) == 0) {
q.add(to);
res.add(to);
num += 1;
}
}
}
if (num != group2items.get(g).size()) return new int[0];
}
int[] ret = new int[res.size()];
for (int i = 0; i < res.size(); i++) ret[i] = res.get(i);
return ret;
}

  

拓扑排序 Topological Sort的更多相关文章

  1. LeetCode编程训练 - 拓扑排序(Topological Sort)

    拓扑排序基础 拓扑排序用于解决有向无环图(DAG,Directed Acyclic Graph)按依赖关系排线性序列问题,直白地说解决这样的问题:有一组数据,其中一些数据依赖其他,问能否按依赖关系排序 ...

  2. 算法与数据结构基础 - 拓扑排序(Topological Sort)

    拓扑排序基础 拓扑排序用于解决有向无环图(DAG,Directed Acyclic Graph)按依赖关系排线性序列问题,直白地说解决这样的问题:有一组数据,其中一些数据依赖其他,问能否按依赖关系排序 ...

  3. 【数据结构与算法Python版学习笔记】图——拓扑排序 Topological Sort

    概念 很多问题都可转化为图, 利用图算法解决 例如早餐吃薄煎饼的过程 制作松饼的难点在于知道先做哪一步.从图7-18可知,可以首先加热平底锅或者混合原材料.我们借助拓扑排序这种图算法来确定制作松饼的步 ...

  4. 拓扑排序 (Topological Sorting)

    拓扑排序(Topological Sorting) 一.拓扑排序 含义 构造AOV网络全部顶点的拓扑有序序列的运算称为拓扑排序(Topological Sorting). 在图论中,拓扑排序(Topo ...

  5. [MIT6.006] 14. Depth-First Search (DFS), Topological Sort 深度优先搜索,拓扑排序

    一.深度优先搜索 它的定义是:递归探索图,必要时要回溯,同时避免重复. 关于深度优先搜索的伪代码如下: 左边DFS-Visit(V, Adj.s)是只实现visit所有连接某个特定点(例如s)的其他点 ...

  6. 拓扑排序(Toposort)

    摘自:https://blog.csdn.net/qq_35644234/article/details/60578189 <图论算法> 1.拓扑排序的介绍 对一个有向无环图(Direct ...

  7. [LeetCode] 207. 课程表(拓扑排序,BFS)

    题目 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总量 ...

  8. BFS (1)算法模板 看是否需要分层 (2)拓扑排序——检测编译时的循环依赖 制定有依赖关系的任务的执行顺序 djkstra无非是将bfs模板中的deque修改为heapq

    BFS模板,记住这5个: (1)针对树的BFS 1.1 无需分层遍历 from collections import deque def levelOrderTree(root): if not ro ...

  9. 拓扑排序(三)之 Java详解

    前面分别介绍了拓扑排序的C和C++实现,本文通过Java实现拓扑排序. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑排序的代码说明 4. 拓扑排序的完整源码和测试程序 转载请注明出处 ...

随机推荐

  1. mysql的Navicat查看数据库的ER图

    1.mysql数据库表间的关系图可以通过navicat查看.

  2. Trove系列(三)—Trove的功能管理功能介绍

    Trove的功能管理功能Trove的功能管理功能包括给各种不同的版本的 datastore 安装不同的 功能. 本管理功能只适用于激活/去活全系统的功能.唯一例外的是数据存储功能列表功能,该功能对所有 ...

  3. Object-C-Foundation-set

    无序集合 哈希表 NSSet *colors=[NSSet setWithObjects:@@"yellow",@"red",@"blue" ...

  4. POJ 1836

    刚开始二分写错了 wa了很久 这个二分 的好好想想 #include <iostream> #include<cstdio> #include<string.h> ...

  5. python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名

    python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名,如果在类中定义的就是类的私有成员. >>> dir(__builtin ...

  6. php mysqli query 查询数据库后读取内容的方法

    php mysqli query 查询数据库后读取内容的方法 <?php$mysqli = new mysqli("localhost", "my_user&quo ...

  7. Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC

    Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC 这两个宏在Qt的源码中随处可见,重要性不言而喻.在 部落格的 Inside Qt Series 系列文章中,他用了3篇文章来讲这个 ...

  8. java service wrapper日志参数设置及优化

    一般在容器比如tomcat/weblogic中运行时,我们都是通过log4j控制日志输出的,因为我们现在很多服务端使用java service wrapper(至于为什么使用jsw,原先是比较排斥使用 ...

  9. 01: Django基础篇

    目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...

  10. 维特比算法Python实现

    前言 维特比算法是隐马尔科夫问题的一个基本问题算法.维特比算法解决的问题是已知观察序列,求最可能的标注序列. 什么是维特比算法? 维特比算法尽管是基于严格的数学模型的算法,但是维特比算法毕竟是算法,因 ...