(十七)拓扑排序算法
在代码具体实现的时候,我们还需要两个辅助的数据结构:
1、邻接表:通过结点的索引,我们能够得到这个结点的后继结点;
2、入度数组:通过结点的索引,我们能够得到指向这个结点的结点个数。
3.入度为0的队列
具体做如下:
1、在开始排序前,扫描对应的存储空间(使用邻接表),将入度为 0 的结点放入队列。
2、只要队列非空,就从队首取出入度为 0 的结点,将这个结点输出到结果集中,并且将这个结点的所有邻接结点(它指向的结点)的入度减 1,在减 1 以后,如果这个被减 1的结点的入度为 0 ,就继续入队。
一、节点、图定义
public class Node {
public Object val;
public int pathIn = 0; // 入链路数量
public Node(Object val) {
this.val = val;
}
}
public class Graph {
// 图中节点的集合
public Set<Node> vertexSet = new HashSet<Node>();
// 相邻的节点,纪录边
public Map<Node, Set<Node>> adjaNode = new HashMap<Node, Set<Node>>();
// 将节点加入图中
public boolean addNode(Node start, Node end) {
if (!vertexSet.contains(start)) {
vertexSet.add(start);
}
if (!vertexSet.contains(end)) {
vertexSet.add(end);
}
if (adjaNode.containsKey(start)
&& adjaNode.get(start).contains(end)) {
return false;
}
if (adjaNode.containsKey(start)) {
adjaNode.get(start).add(end);
} else {
Set<Node> temp = new HashSet<Node>();
temp.add(end);
adjaNode.put(start, temp);
}
end.pathIn++;
return true;
}
}
二、拓扑排序
public class KahnTopo {
//存放结果集
private ArrayList<Node> result=new ArrayList<Node>();
//存放0入度的节点
private Queue<Node> setOfZeroIndregree=new LinkedList<Node>();
private Graph graph;
public KahnTopo(Graph graph)
{
this.graph=graph;
//将图中入度为0的节点放入队列中
for(Node node:this.graph.vertexSet)
{
if(node.pathIn==0)
setOfZeroIndregree.add(node);
}
}
//思路:先找到任何一个没有入度的定点,然后打印该节点,并将它及其边从图中删除,然后对其他部分继续这个操作
public void process()
{
while(!setOfZeroIndregree.isEmpty())
{
Node node=setOfZeroIndregree.poll();//获取并移除
//1.加入到结果集中
result.add(node);
/*
* 2.因为每次删除节点要将以其为出度的边也删除,所以可能邻接表已经删光了
* 为什么不在删邻接表时候return呢
* 因为可能还存在无入度的节点
*
* 在这个例子中看c删除后,邻接表空了,但还有f节点
*/
if(this.graph.adjaNode.keySet().isEmpty()){
return;
}
//3.将以该边为出度的节点 入度-1
for(Node node1:graph.adjaNode.get(node))
{
node1.pathIn--;
if(node1.pathIn==0)
setOfZeroIndregree.add(node1);
}
//3.将该节点从图顶点表中删除
graph.vertexSet.remove(node);
//4.将该节点从临界表中删除
graph.adjaNode.remove(node);
}
//如果此图中还有边,则说明有环
if(!graph.vertexSet.isEmpty())
throw new IllegalArgumentException("has cycle");
}
public static void main(String[] args) {
Node A = new Node("A");
Node B = new Node("B");
Node C = new Node("C");
Node D = new Node("D");
Node E = new Node("E");
Node F = new Node("F");
Graph graph = new Graph();
graph.addNode(A, B);
graph.addNode(B, C);
graph.addNode(B, D);
graph.addNode(D, C);
graph.addNode(E, C);
graph.addNode(C, F);
KahnTopo topo = new KahnTopo(graph);
topo.process();
for(Node temp : topo.result){
System.out.print(temp.val.toString() + "-->");
}
}
}
Leecode207课程表:https://leetcode-cn.com/problems/course-schedule/