https://www.lintcode.com/problem/topological-sorting/my-submissions
问题描述
给定一个有向图,图节点的拓扑排序定义如下:
- 对于图中的每一条有向边 A -> B , 在拓扑排序中A一定在B之前.
- 拓扑排序中的第一个节点可以是图中的任何一个没有其他节点指向它的节点.
针对给定的有向图找到任意一种拓扑排序的顺序
The topological order can be:
[0, 1, 2, 3, 4, 5]
[0, 2, 3, 1, 5, 4]
思路
先遍历所有结点的neighbor列表, 用一个hashmap来记录每个点的入度. 将入度为0的点入队列.
当队列还有结点时候从队列里弹出一个点, 把它的neighbor列表里的节点的入度都-1,如果有入度为0的就继续进入队列。
基本步骤:
1.构造一个队列Q 和 拓扑排序的结果队列R;
2.把所有没有依赖结点(入度为0)的节点放入队列Q;
3.当Q还有结点的时候,执行下面步骤:
3.1 从Q中取出一个结点n(将n从Q中删掉),并放入R(将n加入到结果集中);
3.2 对n每一个邻接点m(n是起点,m是终点);
3.2.1 邻接点m入度-1 (可以理解为 去掉边<结点n,邻接点m>;
3.2.2 如果邻接点m没有依赖结点(入度为0),则把邻接点m放入Q;
java实现
//Definition for Directed graph.
class DirectedGraphNode {
int label;
ArrayList neighbors;
DirectedGraphNode(int x) {
label = x;
neighbors = new ArrayList();
}
};
public class Solution {
/*
* @param graph: A list of Directed graph node
* @return: Any topological order for the given graph.
*/
public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
// write your code here
ArrayList<DirectedGraphNode> results=new ArrayList<>();
if(graph==null || graph.size()==0)
return results;
//1. count indgree 返回<结点,入度>(入读:有多少边指向它)
Map<DirectedGraphNode,Integer> indegree =getIndegree(graph);
//2. topological sorting -bfs 返回入度为0的点
ArrayList<DirectedGraphNode> startnodes=getStartNodes(indegree,graph);
//3. bfs 宽度优先搜索
results=bfs(indegree,startnodes);
if(results.size()==graph.size())//排除有环的图(有环的图不能被拓扑排序) results.size()=0
return results;
return null;
}
//1. count indgree 返回<结点,入度>(入读:有多少边指向它)
private Map<DirectedGraphNode,Integer> getIndegree (ArrayList<DirectedGraphNode> graph){
Map<DirectedGraphNode,Integer> map=new HashMap<DirectedGraphNode,Integer>();
//1,2,4 表示 2, 4 是 1的邻居 A的邻居是B说明A->B,B的入度加+1
for (DirectedGraphNode node:graph){//遍历图中结点
for (DirectedGraphNode current:node.neighbors){//遍历结点的邻居
if(map.containsKey(current))//map中包含结点
map.put(current,map.get(current)+1);//入度加+1
else//map中不包含结点
map.put(current,1);//初始为1
}
}
return map;
}
//2. topological sorting -bfs 返回入度为0的点
private ArrayList<DirectedGraphNode> getStartNodes(Map<DirectedGraphNode,Integer> indegree, ArrayList<DirectedGraphNode> graph) {
ArrayList<DirectedGraphNode> nodes=new ArrayList<>();
for(DirectedGraphNode node: graph){
if(!indegree.containsKey(node))//入度为0 map.containsKey(node)返回false
nodes.add(node);
}
return nodes;
}
//3. bfs 宽度优先搜索
private ArrayList<DirectedGraphNode> bfs(Map<DirectedGraphNode,Integer> indegree, ArrayList<DirectedGraphNode> startnodes){
ArrayList<DirectedGraphNode> order=new ArrayList<>();
Queue<DirectedGraphNode> queue=new LinkedList<>();
for (DirectedGraphNode node: startnodes){ //遍历入度为0的点
order.add(node); //加入结果中
queue.add(node); //加入队列中
}
while (!queue.isEmpty()){ //队列不空
DirectedGraphNode node=queue.poll(); //出栈获取结点
for (DirectedGraphNode neighbor : node.neighbors){ //访问该点的邻居
indegree.put(neighbor,indegree.get(neighbor)-1); //该点的邻居的入度-1(因为访问该点)
if(indegree.get(neighbor)==0){ //邻居入度为0 可以进入队列和结果中
queue.offer(neighbor); //加入结果中
order.add(neighbor); //加入队列中
}
}
}
return order;
}
}