尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

拓扑排序 + 广度优先搜索法实例应用(二)

拓扑排序 + 广度优先搜索法实例应用(二)
📅 发布时间:2026/7/3 6:31:38

上篇文章,我们介绍了使用深度优先搜索实现拓扑排序,根据每个节点搜索完成的顺序反向得到拓扑排序。使用广度优先搜索实现拓扑排序,则可以正向得到拓扑排序。

首先计算每个节点的入度,只有入度为 0 的节点可能是拓扑排序中最前面的节点。当一个节点加入拓扑排序之后,该节点的所有相邻节点的入度都减 1,表示相邻节点少了一条入边。当一个节点的入度变成 0 ,则该节点前面的节点都已经加入拓扑排序,该节点也可以加入拓扑排序。

具体做法是:使用队列存储可以加入拓扑排序的节点,初始时将所有入度为 0 的节点入队列。每次将一个节点出队列并加入拓扑排序中,然后将该节点的所有相邻节点的入度都减 1 ,如果一个相邻节点的入度变成 0 ,则将该相邻节点入队列。重复上述操作,直到队列为空时,广度优先搜索结束。

如果有向图中无环,则每个节点都将加入拓扑排序,因此拓扑排序的长度等于字典中的字母个数。如果有向图中有环,则环中的节点不会加入拓扑排序,因此拓扑排序的长度小于字典中的字母个数。广度优先搜索结束时,判断拓扑排序的长度是否等于字典中的字母个数,即可判断有向图中是否有环。

  • 如果拓扑排序的长度等于字典中的字母个数,则拓扑排序包含字典中的所有字母,返回拓扑排序;
  • 如果拓扑排序的长度小于字典中的字母个数,则有向图中有环,不存在拓扑排序。如果拓扑排序的长度小于字典中的字母个数,则有向图中有环,不存在拓扑排序。

代码

Python3

class Solution: def alienOrder(self, words: List[str]) -> str: g = defaultdict(list) inDeg = {c: 0 for c in words[0]} for s, t in pairwise(words): for c in t: inDeg.setdefault(c, 0) for u, v in zip(s, t): if u != v: g[u].append(v) inDeg[v] += 1 break else: if len(s) > len(t): return "" q = [u for u, d in inDeg.items() if d == 0] for u in q: for v in g[u]: inDeg[v] -= 1 if inDeg[v] == 0: q.append(v) return ''.join(q) if len(q) == len(inDeg) else ""

Java

class Solution { Map<Character, List<Character>> edges = new HashMap<Character, List<Character>>(); Map<Character, Integer> indegrees = new HashMap<Character, Integer>(); boolean valid = true; public String alienOrder(String[] words) { int length = words.length; for (String word : words) { int wordLength = word.length(); for (int j = 0; j < wordLength; j++) { char c = word.charAt(j); edges.putIfAbsent(c, new ArrayList<Character>()); } } for (int i = 1; i < length && valid; i++) { addEdge(words[i - 1], words[i]); } if (!valid) { return ""; } Queue<Character> queue = new ArrayDeque<Character>(); Set<Character> letterSet = edges.keySet(); for (char u : letterSet) { if (!indegrees.containsKey(u)) { queue.offer(u); } } StringBuffer order = new StringBuffer(); while (!queue.isEmpty()) { char u = queue.poll(); order.append(u); List<Character> adjacent = edges.get(u); for (char v : adjacent) { indegrees.put(v, indegrees.get(v) - 1); if (indegrees.get(v) == 0) { queue.offer(v); } } } return order.length() == edges.size() ? order.toString() : ""; } public void addEdge(String before, String after) { int length1 = before.length(), length2 = after.length(); int length = Math.min(length1, length2); int index = 0; while (index < length) { char c1 = before.charAt(index), c2 = after.charAt(index); if (c1 != c2) { edges.get(c1).add(c2); indegrees.put(c2, indegrees.getOrDefault(c2, 0) + 1); break; } index++; } if (index == length && length1 > length2) { valid = false; } } }

复杂度分析

  • 时间复杂度:O(n×L +∣Σ∣) ,其中 n 是数组 words 的长度,即字典中的单词数, L 是字典中的平均单词长度,Σ 是字典中的字母集合。遍历字典构造有向图需要 O(n×L) 的时间,由于有向图包含最多 n−1 条边和 ∣Σ∣ 个节点,因此广度优先搜索需要 O(n +∣Σ∣) 的时间,总时间复杂度是 O(n×L + n +∣Σ∣) = O(n×L +∣Σ∣) 。
  • 空间复杂度:O(n+∣Σ∣) ,其中 n 是数组 words 的长度,即字典中的单词数,Σ 是字典中的字母集合。空间复杂度主要取决于存储有向图需要的空间,有向图包含最多 n−1 条边和 ∣Σ∣ 个节点。

相关新闻

  • 广州市即闪科技有限公司评价
  • 计算机毕业设计之基于javaweb技术与SSM框架的智慧商城平台的设计与实现
  • AI Agent开发实战:核心技术、行业应用与优化策略

最新新闻

  • Obsidian接入国产大模型:Node.js+Git+沙箱的可审计工作流
  • 如何高效使用Windows实时屏幕翻译工具:Translumo实用指南
  • Navicat Mac版无限试用重置终极指南:三种方法免费使用Navicat Premium
  • 从零上手Codex:AI编程助手实战指南与API集成教程
  • 紧急通知:2024下半年软考程序员题型将新增“场景化调试题”,零基础考生最后30天必须掌握的4种逆向读题法
  • 跨越平台壁垒:3分钟掌握多平台资源下载的终极解决方案

日新闻

  • JMeter接口测试实战:从核心元件到复杂场景构建
  • Java Applet版刽子手游戏源码:含完整项目结构、吊杆绘图与胜负逻辑
  • 使用Apache JMeter对RoadRunner PHP应用进行性能测试与调优指南

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号