认识:
一个较大的工程往往被划分成许多子工程,我们把这些子工程称作活动(activity)。在整个工程中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,也就是说,一个子工程的开始是以它的所有前序子工程的结束为先决条件的,但有些子工程没有先决条件,可以安排在任何时间开始。通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。
AOV网的特点:无向无环图,因为如果有环就会有循环依赖,不符合项目特征。
那工程的执行顺序是什么呢,拓扑排序就是工程的执行顺序。
拓扑排序常用来确定一个依赖关系集中,事物发生的顺序。例如,在日常工作中,可能会将项目拆分成A、B、C、D四个子部分来完成,但A依赖于B和D,C依赖于D。为了计算这个项目进行的顺序,可对这个关系集进行拓扑排序,得出一个线性的序列,则排在前面的任务就是需要先完成的任务。
代码实现
package 算法.图.拓扑排序;
import 算法.图.其他结构转换.CreateGraph01;
import 算法.图.其他结构转换.CreateGraphInterface;
import 算法.图.其他结构转换.IntArr;
import 算法.图.基础节点.Graph;
import 算法.图.基础节点.Node;
import java.util.*;
/**
* 拓扑排序
*
*/
public class TopologySort {
public static void main(String[] args) {
//构建图
IntArr matrix = new IntArr();
int[][] arr = {
{1,1,2},
{1,2,3},
{2,1,4},
{3,2,4},
{4,1,5}
};
matrix.setArr(arr);
CreateGraphInterface createGraph = new CreateGraph01();
Graph graph = createGraph.createGraph(matrix);
//输出拓扑排序
List<Node> nodes = sortedTopology(graph);
System.out.println(nodes.toString());
}
/**
* 输出拓扑排序顺序
* @param graph
* @return
*/
public static List<Node> sortedTopology(Graph graph){
//存储节点入度
HashMap<Node,Integer> hashMap = new HashMap<>();
//队列,用于存放入度为0的节点
Queue<Node> queue = new LinkedList<>();
List<Node> list = new ArrayList<>();
//第一次循环 将节点放入map里面,如果有入度为0的放到队列里
for(Node node:graph.nodes.values()){
hashMap.put(node,node.in);
if (node.in == 0) {
queue.add(node);
}
}
//循环队列里的节点直到为空,并且减少map中后续节点的入度,当入度为0的时候 放入队列
while (!queue.isEmpty()){
Node n1 = queue.poll();
for (Node next:n1.nexts) {
Integer in = hashMap.get(next);
in--;
//当后面的节点入度为0的时候 加入到队列
if (in.equals(0)) {
queue.add(next);
}
hashMap.put(next,in);
}
list.add(n1);
}
return list;
}
}