目录
一、原理
1. 引例:207.课程表
就如大学课程安排一样,如果要学习数据结构与算法、机器学习这类课程,肯定要先学习C语言、Python、离散数学、概率论等等,我们将类似的“推导”关系建如下有向简单图⬇️

2. 应用场景
根据节点的入度大小,拓扑排序主要用于处理先后问题(拓扑序列),以及判断图中是否有环的问题;
3. 代码思路
用大小为节点个数的数组记录每个节点的入度,用队列存放入度为0的节点,遍历这些节点,将这些节点指向的节点的入度-1,最后在记录入度减为0的节点,重复上述步骤;
①拓扑序列:在循环过程中向一数组中push入度为0的节点,排在数组前的节点即为入度先被减为0的节点;
②是否存在环:若拓扑序列数组大小等于节点总个数则说明图中无环;反之,这说明图有环
二、代码模板
/*这里用课程表一题的代码当作模板*/
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> g(numCourses);
int in_degree[numCourses]; //记录节点的入度
memset(in_degree, 0, sizeof(in_degree));
for (auto& e : prerequisites) {
int x = e[0], y = e[1]; //建图
g[x].push_back(y);
in_degree[y]++; // x -> y ,则y节点入度+1
}
vector<int> order;
queue<int> q;
for(int i = 0; i < numCourses; i++) if (in_degree[i] == 0) q.push(i); //将入度为0的节点加入到队列中
while (!q.empty()) {
int x = q.front();
q.pop();
order.push_back(x); //push到拓扑序列中
for (auto y : g[x]) {
in_degree[y]--; //x -> y , 即将y入度-1
if (in_degree[y] == 0) q.push(y);
}
}
return order.size() == numCourses; //判断是否有环
}
};
三、练习
1、210.课程表Ⅱ🟢
现在你总共有
numCourses门课需要选,记为0到numCourses - 1。给你一个数组prerequisites,其中prerequisites[i] = [ai, bi],表示在选修课程ai前 必须 先选修bi。
- 例如,想要学习课程
0,你需要先完成课程1,我们用一个匹配来表示:[0,1]。返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。
示例:
输入:numCourses = 2, prerequisites = [[1,0]] 输出:[0,1] 解释:总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为[0,1] 。
解题思路: 与课程表Ⅰ思路基本一样,依次取出入度为0的节点加入到答案数组中,若数组大小与总结点个数不相同,则说明图中有环,返回空数组。

文章介绍了拓扑排序在课程表安排中的应用,展示了如何通过入度计算进行拓扑排序以确定学习顺序,并给出了几个编程题目实例,涉及课程表、图的环检测、矩阵构造以及最小高度树和金币收集问题的解决方法。
最低0.47元/天 解锁文章
785





