熟悉java项目的同学,我可能会比较容易解释这个概念,在java项目中,一般会用到第三方jar包,而这些jar包可能会依赖其他的jar包,这样就形成了拓扑图。而在拓扑中,必定有一个jar包是不依赖其他任何jar包的,也就是入度为零的源节点,而且jar包不能互相形成循环,否则会出问题。
所以拓扑排序适用于有向图,且必有入度为0的节点,不能有环
public class TopologySort {
private static List<Node> sortedTopology(Graph graph){
HashMap<Node,Integer> inMap = new HashMap<>();
LinkedList<Node> zeroQueue = new LinkedList<>();
//将拓扑图中所有节点以及该节点的入度个数存入map中
//将所有初始入度为0的节点存入队列中
for (Node node : graph.nodes.values()) {
inMap.put(node,node.in);
if (node.in == 0){
zeroQueue.add(node);
}
}
List<Node> res = new ArrayList<>();
//遍历队列中的节点,每弹出一个结点,邻接节点的入度减一,如入度边为0,则存入队列中
//循环遍历出所有的节点,按照弹出顺序保存数据,即拓扑顺序,返回数据
while (!zeroQueue.isEmpty()){
Node cur = zeroQueue.poll();
res.add(cur);
for (Node next : cur.nexts) {
inMap.put(next,inMap.get(next)-1);
if (inMap.get(next) == 0){
zeroQueue.add(next);
}
}
}
return res;
}
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
ArrayList<Node> list1 = new ArrayList<>();
list1.add(node2);
list1.add(node3);
node1.nexts = list1;
node1.in = 0;
node1.out = 2;
ArrayList<Node> list2 = new ArrayList<>();
list2.add(node4);
node2.nexts = list2;
node2.in = 2;
node2.out = 1;
ArrayList<Node> list3 = new ArrayList<>();
list3.add(node2);
list3.add(node4);
list3.add(node5);
node3.nexts = list3;
node3.in = 1;
node3.out = 3;
node4.in = 2;
node4.out = 0;
node5.in = 1;
node5.out = 0;
Graph graph = new Graph();
HashMap<Integer, Node> map = new HashMap<>();
map.put(1,node1);
map.put(2,node2);
map.put(3,node3);
map.put(4,node4);
map.put(5,node5);
graph.nodes = map;
List<Node> nodes = sortedTopology(graph);
System.out.println();
}
}