当前位置: 首页 > news >正文

【算法】小白也能懂 · 第 16 节:拓扑排序

在现实生活中,很多任务之间存在依赖关系。比如:你必须先学完 C++ 基础,才能学 STL;必须先编译源文件,才能链接成可执行程序。

拓扑排序就是解决这类「依赖关系排序」问题的经典算法。

1. 什么是拓扑排序?

1.1 问题定义

给定一个有向无环图(DAG),将图中的所有顶点排成一个线性序列,使得对于图中任意一条边 (u, v),顶点 u 在序列中都出现在顶点 v 之前。

用大白话说:把有依赖关系的任务排个顺序,确保每个任务都在它依赖的任务之后执行

1.2 生活中的例子

选课系统

数据结构 → 算法设计 → 高级算法 ↓ ↓ 操作系统 → 编译原理

这个依赖关系的拓扑排序结果可以是:

  • 数据结构 → 操作系统 → 算法设计 → 编译原理 → 高级算法
  • 数据结构 → 算法设计 → 操作系统 → 编译原理 → 高级算法

注意:拓扑排序的结果可能不唯一,只要满足依赖关系即可。

1.3 关键性质

  • 只有有向无环图(DAG)才有拓扑排序
  • 如果图中有环,则不存在拓扑排序(循环依赖无法解决)
  • 拓扑排序可以用来检测图中是否有环

2. Kahn 算法(BFS 方法)

2.1 核心思想

Kahn 算法的思路非常直观:

  1. 找到所有入度为 0的顶点(没有依赖的顶点)
  2. 将它们加入结果序列
  3. 从图中删除这些顶点和它们的边
  4. 重复步骤 1-3,直到所有顶点都被处理

如果最终结果包含所有顶点,则排序成功;如果还有剩余顶点,说明图中有环。

2.2 图解过程

假设有如下图:

5 → 0 ← 4 ↓ ↓ 2 → 3 → 1

步骤 1:找到入度为 0 的顶点:5, 4

  • 结果序列:[5, 4]

步骤 2:删除 5 和 4 的出边,更新入度

  • 顶点 0 的入度从 2 变为 0
  • 顶点 2 的入度从 1 变为 0

步骤 3:找到入度为 0 的顶点:0, 2

  • 结果序列:[5, 4, 0, 2]

步骤 4:删除 0 和 2 的出边,更新入度

  • 顶点 1 的入度从 1 变为 0
  • 顶点 3 的入度从 1 变为 0

步骤 5:找到入度为 0 的顶点:1, 3

  • 结果序列:[5, 4, 0, 2, 1, 3]

2.3 代码实现

#include<iostream>#include<vector>#include<queue>usingnamespacestd;vector<int>topologicalSort(intn,vector<vector<int>>&edges){// 构建邻接表和入度数组vector<vector<int>>graph(n);vector<int>inDegree(n,0);for(auto&edge:edges){intfrom=edge[0];intto=edge[1];graph[from].push_back(to);inDegree[to]++;}// 将所有入度为 0 的顶点加入队列queue<int>q;for(inti=0;i<n;i++){if(inDegree[i]==0){q.push(i);}}vector<int>result;while(!q.empty()){intnode=q.front();q.pop();result.push_back(node);// 删除该顶点的所有出边for(intneighbor:graph[node]){inDegree[neighbor]--;// 如果入度变为 0,加入队列if(inDegree[neighbor]==0){q.push(neighbor);}}}// 检测是否有环if(result.size()!=n){return{};// 有环,返回空数组}returnresult;}intmain(){// 示例:课程依赖关系// 0: 数据结构, 1: 算法设计, 2: 操作系统// 3: 编译原理, 4: 高级算法vector<vector<int>>edges={{0,
http://www.jsqmd.com/news/905807/

相关文章:

  • 避开次谐波振荡!深入浅出解析电流模式Buck的斜坡补偿与环路稳定
  • 评测全网10款主流降AI率软件:只选真正管用的那一款! - 降AI小能手
  • Windows 11让你头疼?这个开源工具能让你找回熟悉的桌面体验
  • DLSS Swapper终极指南:一键切换游戏超采样版本,免费提升显卡性能
  • Navicat Mac版无限试用重置:3种终极解决方案告别14天限制
  • ROS Noetic下,用Gazebo和ros_control让三轴机械臂小车动起来(附完整配置文件)
  • 【Claude私有化部署生死线】:从模型量化精度损失率、KV Cache内存膨胀系数到审计日志完整性验证——金融级落地必查清单
  • 企业主选弯头厂家踩过的坑:五家主流厂商怎么选 - 速递信息
  • 2026 降AIGC工具实测盘点:实测靠谱,毕业党救急宝典
  • DDrawCompat完整指南:5分钟让经典Windows游戏在现代系统重生
  • LAMMPS模拟石墨烯拉伸:除了velocity,试试这个更省事的deform命令(附完整in文件)
  • Python日志系统详解
  • 从Excel到MATLAB:手把手教你处理实验数据并完成最小二乘拟合(避坑指南)
  • 告别双系统!在Win11上用WSL2搭建Ubuntu 18.04 + ROS Melodic开发环境(附网络问题终极解决方案)
  • PS 平面图制作立体感教程 4 种实用方法全解析
  • 别只看版本号!思科show version命令输出的这5个隐藏信息,排错时能救急
  • ATtiny85软件PWM驱动RGB氛围灯:中断、防抖与电源设计全解析
  • 从PID控制到反应轮:自制自平衡立方体的完整工程实践
  • 别再用tmux了!Claude Code搭配这三个工具,我一天干完一周的活
  • 抖音怎么下载视频无水印?2026年2款免费微信小程序实测推荐 - 速递信息
  • 保姆级教程:在博途V14中手把手配置S7-1500T与V90 PN的PROFINET通信(含HSP安装避坑)
  • Gemini投资者关系管理效能跃迁路径(2024监管新规+AI工具深度整合版)
  • Arduino驱动WS2811灯带:从硬件连接到动态光效实现
  • 别再纠结了!gtsummary vs compareGroups:R语言画基线表到底该选谁?
  • 大型项目弯头厂家选型参考:五个决策步骤与案例解析 - 速递信息
  • 咸阳本地热水器维修 全城就近上门质保一年 - GrowthUME
  • 如何快速提升英雄联盟游戏效率:终极自动化工具完整指南
  • 6G智能超表面优化:从信道可编程到能效与安全性能提升
  • 别再死记ResNet结构了!用PyTorch手搓一个ResNet-18,带你彻底搞懂残差连接
  • STM32 HAL库三LED九种模式闪烁项目实战:从GPIO原理到工程优化