「算法」拓扑排序(货真价实,童叟无欺)

「算法」拓扑排序(货真价实,童叟无欺)_第1张图片

文章目录

  • 什么是拓扑排序
  • 模拟
  • 代码实现
      • BFS
      • DFS

什么是拓扑排序

 对一个有向无环图 ( D i r e c t e d A c y c l i c G r a p h 简 称 D A G ) (Directed Acyclic Graph简称DAG) (DirectedAcyclicGraphDAG) G G G进行拓扑排序,是将 G G G中所有顶点排成一个线性序列,使得图中任意一对顶点 u u u v v v,若边 < u , v > ∈ E ( G ) ∈E(G) <u,v>E(G),则 u u u在线性序列中出现在 v v v之前。通常,这样的线性序列称为满足拓扑次序 ( T o p o l o g i c a l O r d e r ) (Topological Order) (TopologicalOrder)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
                                    —摘自度娘
 简单的来说,我们就找到一个 ( ( (或多个 ) ) )起点,遍历所有能遍历的点,遍历的顺序就是拓扑排序。


模拟

 下面是一个有向无环图,我们来遍历一下,感受一下

1
2
3
4
5

 取出唯一一个入度为0的点— 1 1 1
 删除所有连接 1 1 1的边

2
3
4
5

 取出两个入度为0的点— 2 、 3 2、3 23
 删除所有连接 2 、 3 2、3 23的边

4
5

 取出两个入度为0的点— 4 4 4
 删除所有连接4的边

5

 取出两个入度为0的点— 5 5 5
 图中已经没有点了,遍历结束


最终的顺序为 : 1 、 2 、 3 、 4 、 5 ( :1、2、3、4、5( :12345(不唯一 ) ) )

代码实现

BFS

 通过上面的描述相信大家都能想到BFS的方法, 我们用一个队列来储存入度为0的点,用 i n [ ] in[] in[]来储存每个点的入度, e d g e [ ] edge[] edge[] ( v e c t o r (vector (vector ) ) )来储存边的连接与否。

bool TopoSort() {
	queue <int > q;
	vector <int > ans;
	for (int i = 1; i <= n; i ++) {
		if (in[i] == 0) {
			q.push(i);
		}
	}
	while (q.size()) {
		int U = q.front();
		q.pop();
		ans.push_back(U);
		for (vector <int > :: iterator it = edge[U].begin(); it != edge[U].end(); it ++) {
			in[*it] --;
			if (in[*it] == 0) {
				q.push(*it);
			} 
		}
	}
	if (ans.size() == n) {				//判断是否存在环,如果存在环,就会使得入度为0的点减少
		for (vector <int > :: iterator it = ans.end() - 1; it != ans.begin() - 1; it --) {
			printf("%d ", (*it));
		}
		return true;
	}
	return false;
}

「算法」拓扑排序(货真价实,童叟无欺)_第2张图片

DFS

bool dfs(int u){
    c[u] = -1; 					//标记为正在访问
    for (int v = 1; v <= n; v ++)
    	if (G[u][v]) {
        if (nows[v] < 0) { return false; }				//正在访问,退出
        else if (!nows[v] && !dfs(v)) { return false; }				//访问过且访问失败,退出
    }
    nows[u] = 1;				//标记为访问过
    ans[-- t] = u;				//倒序储存
    return true;
}
bool TopoSort() {
    t = n;
    memset(ans, 0, sizeof(ans));
    for (int u = 1; u <= n; u ++) {
        if (!ans[u]) {				//判断是否未访问
            if (!dfs(u)) { return false; }
        }
    }
    return true;
}

你可能感兴趣的:(算法,拓扑排序,算法,c++)