拓扑排序序列
原理
Proposition. A digraph has a topological order if and only if it is a DAG.
Proposition. Reverse postorder in a DAG is a topological sort.
完整源码
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <map>
using namespace std;
int V, E;
//有向图
map<int, vector<int>> G;
bool marked[100]; // v 是否已经被访问过?
queue<int> postorder; // 后序序列
void dfs(int v) {
marked[v] = true;
for(vector<int>::iterator ii = G[v].begin(); ii != G[v].end(); ii++) {
int w = *ii;
if(!marked[w]) dfs(w);
}
postorder.push(v);
}
void topological() {
for (int v = 0; v < V; v++)
if (!marked[v]) dfs(v);
cout << "a topological order : " << endl;
stack<int> reverse;
while(!postorder.empty()) {
reverse.push(postorder.front());
postorder.pop();
}
while(!reverse.empty()) {
cout << reverse.top() << " ";
reverse.pop();
}
}
void readData() {
cin >> V >> E;
for(int i = 0 ; i < E ;i++)
{
int v, w;
cin >> v >> w;
G[v].push_back(w);
}
}
void showData() {
cout << "Digraph : " << endl;
for(int v = 0; v < V; v++)
{
cout << v << " : ";
for(vector<int>::iterator ii = G[v].begin(); ii != G[v].end(); ii++)
cout << v << "->" << *ii << " ";
cout << endl;
}
system("pause");
}
int main()
{
readData();
showData();
topological();
}
模拟数据
测试运行
6
6
0 3
3 4
4 5
0 1
1 2
2 4
Digraph :
0 : 0->3 0->1
1 : 1->2
2 : 2->4
3 : 3->4
4 : 4->5
5 :
请按任意键继续. . .
a topological order :
0 1 2 3 4 5 --------------------------------
Process exited after 1.523 seconds with return value 0
请按任意键继续. . .
拓扑排序存在的前提
- 没有环
后序序列
void dfs(int v) {
marked[v] = true;
for(vector<int>::iterator ii = G[v].begin(); ii != G[v].end(); ii++) {
int w = *ii;
if(!marked[w]) dfs(w);
}
postorder.push(v); //* 放在这里
}
postorder
是一个queue
,就是放在dfs
的最后;
逆后序
void topological() {
/* 1.开始DFS搜索 */
for (int v = 0; v < V; v++)
if (!marked[v]) dfs(v);
cout << "a topological order : " << endl;
/* 2.后序序列压入栈 */
stack<int> reverse;
while(!postorder.empty()) {
reverse.push(postorder.front());
postorder.pop();
}
/* 3.栈再输出就是逆后序了 */
while(!reverse.empty()) {
cout << reverse.top() << " ";
reverse.pop();
}
}
逆后序不是前序
- 前序 (中 左 右) :
0 1 2 3 4
- 后序 (左 右 中 ) :
1 3 4 2 0
- 逆后序 (后序求反) :
0 2 4 3 1
逆后序
- 没有环,就可以变成树的形式;
- 后序序列是往一个队列里去存的,队列是
FIFO
(先进先出); DFS
是一个递归过程,那么先进入这个队列的顶点,左顶点(右顶点)都会比中顶点更先,也就是被指向的顶点会先进入的这个队列;- 拓扑排序的起点是一个入度为零的点,也就是不被任何顶点指向的点,一定是一个中顶点(也就是树里的根),所以只要将后序序列求个反,得到的必然是一串指出的顶点,也就是拓扑序列;
- 前序序列失效,不能充当拓扑排序序列可以见参考引用[3](或者点我);
引用参考
[1] C++ STL queue
http://www.cplusplus.com/reference/queue/queue/push/[2] algs4 后序序列 逆后序序列
http://algs4.cs.princeton.edu/42digraph/DepthFirstOrder.java.html[3]前序序列不能保证找到拓扑排序序列
https://www.zhihu.com/question/28549004/answer/41236788