在计算机科学中,拓扑排序(Topological Sorting)是一种对有向无环图(DAG, Directed Acyclic Graph)进行线性排序的算法。它广泛应用于任务调度、课程安排、依赖解析等场景。本教程将带你从零开始,用Java语言实现拓扑排序,并确保即使是编程小白也能轻松理解。
想象你正在学习一系列课程,有些课程必须在其他课程之后才能学习(例如:要学“数据结构”,你得先学“Java基础”)。这些课程之间的依赖关系可以用一个有向图表示。如果这个图中没有循环依赖(即不会出现A依赖B,B又依赖A的情况),那么我们就可以对其进行拓扑排序,得到一个合法的学习顺序。

拓扑排序的关键在于:每次选择一个入度为0(即没有任何前置依赖)的节点,将其加入结果序列,并从图中移除该节点及其所有出边。重复此过程,直到图中没有节点为止。
如果最终结果中的节点数量少于原图的节点总数,说明图中存在环,无法进行拓扑排序。
下面我们将使用Kahn算法来实现拓扑排序。该算法基于广度优先搜索(BFS)的思想,非常适合初学者理解。
import java.util.*;public class TopologicalSort { // 使用邻接表表示图 private Map<Integer, List<Integer>> graph; private int numVertices; public TopologicalSort(int vertices) { this.numVertices = vertices; graph = new HashMap<>(); for (int i = 0; i < vertices; i++) { graph.put(i, new ArrayList<>()); } } public void addEdge(int from, int to) { graph.get(from).add(to); } public List<Integer> topologicalSort() { // 计算每个节点的入度 int[] inDegree = new int[numVertices]; for (int u : graph.keySet()) { for (int v : graph.get(u)) { inDegree[v]++; } } // 将所有入度为0的节点加入队列 Queue<Integer> queue = new LinkedList<>(); for (int i = 0; i < numVertices; i++) { if (inDegree[i] == 0) { queue.offer(i); } } List<Integer> result = new ArrayList<>(); // BFS处理 while (!queue.isEmpty()) { int u = queue.poll(); result.add(u); // 移除u的所有出边 for (int v : graph.get(u)) { inDegree[v]--; if (inDegree[v] == 0) { queue.offer(v); } } } // 检查是否存在环 if (result.size() != numVertices) { System.out.println("图中存在环,无法进行拓扑排序!"); return new ArrayList<>(); } return result; } public static void main(String[] args) { TopologicalSort g = new TopologicalSort(6); g.addEdge(5, 2); g.addEdge(5, 0); g.addEdge(4, 0); g.addEdge(4, 1); g.addEdge(2, 3); g.addEdge(3, 1); List<Integer> order = g.topologicalSort(); System.out.println("拓扑排序结果: " + order); }}
拓扑排序在实际开发中非常有用,例如:
通过本教程,你已经掌握了如何用Java语言实现拓扑排序算法,并理解了它在有向无环图排序中的核心作用。无论你是准备面试还是开发实际项目,这项技能都非常实用。
记住:拓扑排序只适用于有向无环图(DAG)。如果你的图中存在环,算法会明确告诉你无法排序。
希望这篇Java图论教程对你有所帮助!动手试试修改代码,添加自己的测试用例吧。
本文由主机测评网于2025-12-17发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025128946.html