问题描述:如下图所示,在有向图中,如何将所有节点排序,使得节点满足其在下一个节点之前,可能存在多种解,只需要返回一个即可。
DFS: 遍历节点过程中,将节点化为三种状态:在搜索中,未搜索,已搜索。每次取未搜索过的节点,依次沿着其下一个节点,深度优先搜索,直到没有下一个节点。之后将已搜索过的节点添加到栈中。
tip: 当有向图存在环时,下一个节点状态为在搜索中,此时停止遍历。
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
public class TopologySort {
static List<List<Integer>> nextNode;
static int[] visit;
static boolean valid; // 判断是否有环
static Deque<Integer> res;
public static void main(String[] args) {
int[][] preNode = new int[][]{{1,2},{1,4},{4,5},{5,6},{2,3},{3,6}};
int numNode = 6+1;
boolean isValid = topologySort(numNode, preNode);
System.out.println(isValid);
while(!res.isEmpty()) {
System.out.print(res.poll() + " ");
}
}
public static boolean topologySort(int numNode, int[][] preNode) {
nextNode = new ArrayList<List<Integer>>();
visit = new int[numNode];
for (int i = 0; i < numNode; i++) {
nextNode.add(new ArrayList<>());
}
for (int i = 0; i < preNode.length; i++) {
nextNode.get(preNode[i][0]).add(preNode[i][1]);
}
valid = true;
res = new LinkedList<>();
for (int i = 1; i < numNode && valid; i++) {
if(visit[i] == 0)
dfs(i);
}
return valid;
}
public static void dfs(int u) {
visit[u] = 1;
for (int v: nextNode.get(u)) {
if(visit[v] == 0){
dfs(v);
if(!valid) {
return;
}
} else if(visit[v] == 1) {
valid = false;
return;
}
}
visit[u] = 2;
res.push(u);
}
}
BFS: 使用队列来处理遍历,每次取入度为0的节点,如上图所示节点0开始,并将其所有的下一个节点的入度减一,后依次取入度为0的节点,直到没有入度为0的节点。
tip: 当有向图中存在环时,最后剩下的节点入度不为0;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
public class TopologySort {
static List<List<Integer>> nextNode;
static int[] inNodes;
static Deque<Integer> queue;
static Deque<Integer> ans;
public static void main(String[] args) {
int[][] preNode = new int[][]{{1,2},{1,4},{4,5},{5,6},{2,3},{3,6}};
int numNode = 6+1;
boolean isValid = topologySort(numNode, preNode);
System.out.println(isValid);
while(!ans.isEmpty()) {
System.out.print(ans.poll() + " ");
}
}
public static boolean topologySort(int numNode, int[][] preNode) {
nextNode = new ArrayList<List<Integer>>();
inNodes = new int[numNode];
for (int i = 0; i < numNode; i++) {
nextNode.add(new ArrayList<>());
}
for (int i = 0; i < preNode.length; i++) {
nextNode.get(preNode[i][0]).add(preNode[i][1]);
inNodes[preNode[i][1]]++;
}
queue = new LinkedList<>();
for (int i = 1; i < numNode; i++) {
if(inNodes[i] == 0) {
queue.offer(i);
}
}
ans = new LinkedList<>();
while(!queue.isEmpty()) {
int u = queue.poll();
ans.offer(u);
for(int v: nextNode.get(u)) {
inNodes[v]--;
if(inNodes[v] == 0) {
queue.offer(v);
}
}
}
return ans.size() == numNode-1;
}
}