0

0

如何正确构建有向图的邻接表:拓扑排序中边方向的核心逻辑

碧海醫心

碧海醫心

发布时间:2026-01-11 10:04:45

|

481人浏览过

|

来源于php中文网

原创

如何正确构建有向图的邻接表:拓扑排序中边方向的核心逻辑

在拓扑排序(如课程表问题)中,邻接表必须按“依赖源 → 依赖目标”方向构建(即 prerequisite → course),才能支持高效正向遍历;若反向构建(course → prerequisite),则每次查找后续节点需全表扫描,时间复杂度从 o(1) 退化为 o(n)。

拓扑排序的本质是模拟依赖流的正向传播过程:从无前置依赖的节点(入度为 0)出发,逐步访问其所有直接后继,并更新它们的依赖状态。因此,邻接表的设计必须服务于这一“源 → 目标”的遍历逻辑。

✅ 正确建图:prerequisite → course(推荐且标准)

这表示“完成 prerequisite 后,可解锁 course”,即图中存在一条有向边 prerequisite → course。该设计使 BFS/DFS 能自然推进:

  • 入度为 0 的节点(如课程 0)作为起点;
  • 查找其邻接节点(adjMap.get(0) 返回 [1, 2]),即“0 能开启哪些课?”——答案直接可得;
  • 每次处理一个节点,仅需常数时间获取全部后继。
// 正确:prerequisite → course
private Map> createAdjacencyList(int[][] prerequisites) {
    Map> adjMap = new HashMap<>();
    for (int[] edge : prerequisites) {
        int course = edge[0];      // 目标课程(被依赖者)
        int prereq = edge[1];       // 前置课程(依赖源)
        adjMap.computeIfAbsent(prereq, k -> new ArrayList<>()).add(course);
    }
    return adjMap;
}

❌ 错误建图:course → prerequisite

若定义为 course → [prereq1, prereq2],语义上虽符合“某课依赖哪些先修课”,但与拓扑排序的执行流相悖:

ClippingMagic
ClippingMagic

魔术般地去除图片背景

下载
  • 起点(入度为 0 的课)仍可识别;
  • 但要找出“哪些课依赖当前课?”,需遍历整个邻接表或额外维护反向索引,每次查找后继代价为 O(V+E),严重拖慢性能。
? 关键原则:邻接表的键(key)应为遍历的“出发点”,值(value)为“可达的目标”。拓扑排序从无依赖者出发、走向被依赖者,故边方向必须是 依赖源 → 依赖目标。

补充说明:入度数组的构建逻辑

入度统计必须与邻接表方向严格一致:

  • 每条边 prereq → course 意味着 course 的入度 +1;
  • prereq 自身入度不受此边影响(除非它在其他边中作为目标出现)。
Map indegree = new HashMap<>();
// 初始化所有出现过的课程(含前置和目标)
for (int[] e : prerequisites) {
    indegree.put(e[0], 0); // course
    indegree.put(e[1], 0); // prereq
}
// 统计每门课作为 target 出现的次数
for (int[] e : prerequisites) {
    indegree.merge(e[0], 1, Integer::sum); // e[0] 是被依赖者,入度+1
}

总结:三步建图心法

  1. 明确语义方向:问自己“算法从哪开始?往哪走?”——拓扑排序是“从因到果”,边必须是 原因 → 结果(即 prereq → course);
  2. 邻接表服务遍历:adjMap.get(u) 应直接返回所有 v,满足 u → v,且 v 是下一步待处理节点;
  3. 入度与边对齐:每条 u → v 边,只增加 v 的入度,不改变 u 的入度。

遵循此逻辑,不仅适用于课程表问题,也普适于所有基于依赖关系的 DAG 拓扑排序场景(如任务调度、编译依赖解析、包安装顺序等)。

相关专题

更多
页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

397

2023.08.14

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

78

2026.01.09

c++框架学习教程汇总
c++框架学习教程汇总

本专题整合了c++框架学习教程汇总,阅读专题下面的文章了解更多详细内容。

46

2026.01.09

学python好用的网站推荐
学python好用的网站推荐

本专题整合了python学习教程汇总,阅读专题下面的文章了解更多详细内容。

119

2026.01.09

学python网站汇总
学python网站汇总

本专题整合了学python网站汇总,阅读专题下面的文章了解更多详细内容。

11

2026.01.09

python学习网站
python学习网站

本专题整合了python学习相关推荐汇总,阅读专题下面的文章了解更多详细内容。

14

2026.01.09

俄罗斯手机浏览器地址汇总
俄罗斯手机浏览器地址汇总

汇总俄罗斯Yandex手机浏览器官方网址入口,涵盖国际版与俄语版,适配移动端访问,一键直达搜索、地图、新闻等核心服务。

71

2026.01.09

漫蛙稳定版地址大全
漫蛙稳定版地址大全

漫蛙稳定版地址大全汇总最新可用入口,包含漫蛙manwa漫画防走失官网链接,确保用户随时畅读海量正版漫画资源,建议收藏备用,避免因域名变动无法访问。

353

2026.01.09

php学习网站大全
php学习网站大全

精选多个优质PHP入门学习网站,涵盖教程、实战与文档,适合零基础到进阶开发者,助你高效掌握PHP编程。

42

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号