说实话,在数据结构中,拓扑排序我掌握的不是很好,今天在lintCode上面做了关于拓扑排序的题,才开始还是有点懵逼,后面的渐渐的分析,还是做出来了。在这里只是做一个记录,随便巩固一下深搜和广搜。
题意:
给定一个有向图,图节点的拓扑排序被定义为:
对于每条有向边A--> B,则A必须排在B之前
拓扑排序的第一个节点可以是任何在图中没有其他节点指向它的节点
找到给定图的任一拓扑排序
注意事项:
你可以假设图中至少存在一种拓扑排序
由于lintCode上面的图片不能显示出来,所以样例就看不到,这里就不再贴出样例,各位大佬可以yy。
1.广搜算法
由于拓扑排序是数据结构中比较重要的部分,大家都知道,这里就不再讲解它的解题思路
//需要注意的是,这里的图使用领接表来保存
public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
ArrayList<DirectedGraphNode> list = new ArrayList<>();
if (graph == null || graph.size() == 0) {
return list;
}
//遍历领接表,用map来保存每个点的入度是多少
Map<DirectedGraphNode, Integer> map = new HashMap<>();
for (DirectedGraphNode n : graph) {
if(!map.containsKey(n)) {
map.put(n, 0);
}
for (DirectedGraphNode n1 : n.neighbors) {
if (!map.containsKey(n1)) {
map.put(n1, 1);
} else {
int i = map.get(n1) + 1;
map.remove(n1);
map.put(n1, i);
}
}
}
Queue<DirectedGraphNode> queue = new LinkedList<>();
Set<DirectedGraphNode> set = map.keySet();
for (DirectedGraphNode key : set) {
if (map.get(key) == 0) {
queue.offer(key);
}
}
//广搜
while (!queue.isEmpty()) {
DirectedGraphNode node = queue.poll();
list.add(node);
for (DirectedGraphNode n : node.neighbors) {
int i = map.get(n) - 1;
map.remove(n);
if (i >= 0) {
map.put(n, i);
}
if (i == 0) {
queue.offer(n);
}
}
}
return list;
}
2.深搜算法
private ArrayList<DirectedGraphNode> list = new ArrayList<>();
public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
if (graph == null || graph.size() == 0) {
return list;
}
Map<DirectedGraphNode, Integer> map = new HashMap<>();
for (DirectedGraphNode n : graph) {
if (!map.containsKey(n)) {
map.put(n, 0);
}
for (DirectedGraphNode n1 : n.neighbors) {
if (!map.containsKey(n1)) {
map.put(n1, 1);
} else {
int i = map.get(n1) + 1;
map.remove(n1);
map.put(n1, i);
}
}
}
Set<DirectedGraphNode> set = map.keySet();
for (DirectedGraphNode key : set) {
//一旦它的入度为0,那么搜索它
if (map.get(key) == 0) {
list.add(key);
dfs(key, map);
break;
}
}
return list;
}
public void dfs(DirectedGraphNode node, Map<DirectedGraphNode, Integer> map) {
for (DirectedGraphNode n : node.neighbors) {
int i = map.get(n) - 1;
map.replace(n, i);
if(i == 0) {
//记得这里将入度为0的节点置为-1,因为上面的遍历入度为0的node是,可能会重复搜索
map.replace(n, -1);
list.add(n);
dfs(n, map);
}
}
}