拓扑排序
对一个有向无环图( Directed Acyclic Graph ,简称 DAG ) G 进行拓扑排序,是将 G 中所有顶点排成一个线性序列,使得图中任意一对顶点 u 和 v ,若边 <u,v>∈E(G) ,则 u 在线性序列中出现在 v 之前。通常,这样的线性序列称为拓扑序列。
Kahn算法
Kahn 算法利用了贪心
思想。核心思想是:每个顶点的入度表示了该顶点依赖多个个其他顶点,如果某个顶点的入度为 0 ,说明该顶点没有依赖的顶点了。因此每次去掉入度为 0 的顶点,并放入结果数组中,直到没有入度为 0 的顶点。得到的结果就是拓扑排序后的线性序列。
算法步骤:
- 维护一个队列(栈),里面始终存放入度为0的顶点
- 将所有入度为 0 的顶点入队
- 从队列(栈)中取出一个顶点 x ,并把 x 的编号存入结果集中
- 对于刚才取出的顶点 x , x 所指向的所有顶点的入度减1(对应于图中就是把所有以 x 为起点的有向边全部去掉),并检查减 1 之后入度是否为 0 ,若是,则放入队列(栈)中
- 重复步骤3、4,直到队列(栈)为空
代码实现:
/*
Author: ZL
Description: Kahn
Date: 2021-8
*/
std::vector<std::vector<int>> graph; //用邻接矩阵来存储图
std::vector<int> result; //result数组存储拓扑排序后的结果
void Kahn() {
int m = graph.size();
std::vector<int> inD(m, 0); //入度表,记录每个顶点的入度
for (int i = 0; i < m; ++i) {
for (int j = 0; j < m; ++j) {
if (graph[i][j] == 1) {
inD[j]++;
}
}
}
std::queue<int> que;
for (int i = 0; i < m; ++i) {
if (inD[i] == 0) {
que.push(i);
}
}
while (!que.empty()) {
int t = que.front();
que.pop();
result.push_back(t);
for (int i = 0; i < m; ++i) {
if (graph[t][i] == 1 && --inD[i] == 0) {
que.push(i);
}
}
}
}