import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
* 该类演示拓扑排序的算法与实现
*/
public class Main {
public static List<Integer> topologicalSorting(int n, int[][] vertexMatrix) {
// 创建一个用于输出拓扑排序结果的集合,入度为0的顶点会一次添加到此列表中
List<Integer> topoRes = new ArrayList<>();
// 1、首先是要创建一个数组对象,用于保存结点的入度
int[] inDegree = new int[n];
// 遍历所有所有子结点的,得到结点的入度并保存
for (int i = 0; i < vertexMatrix.length; i++) {
int child = vertexMatrix[i][1];
inDegree[child]++;
}
// 创建一个队列,用于将入度为0的顶点放入其中
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (inDegree[i] == 0) {
queue.offer(i);
}
}
// 从队列中取值
while (!queue.isEmpty()) {
int curr = queue.poll(); // 取出
topoRes.add(curr); // 添加到输出结果中
// 循环遍历,找出父结点等于curr的结点,将他的子节点的入度减去1
// 因为已经从有向图中取出了父节点
for (int i = 0; i < vertexMatrix.length; i++) {
int parent = vertexMatrix[i][0];
// 判断,如果父节点等于curr,则将其子节点的入度减去1
if (parent == curr) {
int child = vertexMatrix[i][1];
inDegree[child]--;
// 子节点的入度减去1之后,如果入度为0,则可以添加到队列
if (inDegree[child] == 0) {
queue.offer(child);
}
}
}
}
// 如果对有向图进行拓扑排序后,结果集合的大小小于节点数,说明该有向图不是“有向无环图”
// 那么无法进行拓扑排序,返回空集合。
return topoRes.size() == n ? topoRes : new ArrayList<>();
}
public static void main(String[] args) {
// write your code here
int n = 5;
int[][] vertexMatrix = {{0, 1}, {0, 2}, {1, 2}, {1, 3}, {2, 3}, {4, 3}, {2, 4}};
System.out.println(topologicalSorting(n, vertexMatrix));
}
}