Java 语言 拓扑排序实现 有向无环图的节点排序

Java阿木 发布于 2025-06-25 11 次阅读


Java实现有向无环图(DAG)的拓扑排序

拓扑排序是一种对于有向无环图(Directed Acyclic Graph,DAG)的节点排序算法,它能够将图中的所有顶点排成一个线性序列,使得对于图中任意有向边(u, v),都有u在v之前。拓扑排序在计算机科学中有着广泛的应用,例如在构建项目依赖关系、课程安排、任务调度等方面。

本文将围绕Java语言,详细讲解如何实现有向无环图的拓扑排序。我们将从基本概念入手,逐步深入到具体的代码实现。

1. 基本概念

1.1 有向无环图(DAG)

有向无环图是一种特殊的图,它没有环(即不存在从某个顶点出发,经过一系列的边,最终回到该顶点的情况)。在DAG中,每个顶点都有入度和出度,入度表示指向该顶点的边的数量,出度表示从该顶点出发的边的数量。

1.2 拓扑排序

拓扑排序的目标是将DAG中的所有顶点按照一定的顺序排列,使得对于图中任意有向边(u, v),都有u在v之前。

2. 拓扑排序算法

拓扑排序算法有多种实现方式,以下是两种常见的算法:

2.1 拓扑排序算法一:Kahn算法

Kahn算法是一种基于广度优先搜索(BFS)的拓扑排序算法。其基本思想是:

1. 计算所有顶点的入度,并将入度为0的顶点加入一个队列中。

2. 队列不为空时,从队列中取出一个顶点,将其加入拓扑排序结果中,并更新其相邻顶点的入度。

3. 如果相邻顶点的入度变为0,则将其加入队列中。

4. 重复步骤2和3,直到队列为空。

2.2 拓扑排序算法二:DFS算法

DFS算法是一种基于深度优先搜索(DFS)的拓扑排序算法。其基本思想是:

1. 从任意一个顶点开始,进行DFS遍历。

2. 在DFS过程中,将访问过的顶点加入一个栈中。

3. 遍历完成后,将栈中的顶点依次出栈,即为拓扑排序结果。

3. Java实现

下面分别使用Kahn算法和DFS算法在Java中实现拓扑排序。

3.1 Kahn算法实现

java

import java.util.;

public class TopologicalSortKahn {


public static List<Integer> topologicalSortKahn(int[][] edges, int numVertices) {


List<Integer> result = new ArrayList<>();


int[] inDegree = new int[numVertices];


Queue<Integer> queue = new LinkedList<>();

// 计算所有顶点的入度


for (int[] edge : edges) {


inDegree[edge[1]]++;


}

// 将入度为0的顶点加入队列


for (int i = 0; i < numVertices; i++) {


if (inDegree[i] == 0) {


queue.offer(i);


}


}

// 队列不为空时,进行BFS遍历


while (!queue.isEmpty()) {


int vertex = queue.poll();


result.add(vertex);

// 更新相邻顶点的入度


for (int[] edge : edges) {


if (edge[0] == vertex) {


inDegree[edge[1]]--;


if (inDegree[edge[1]] == 0) {


queue.offer(edge[1]);


}


}


}


}

return result;


}

public static void main(String[] args) {


int[][] edges = {{0, 1}, {1, 2}, {2, 3}, {3, 4}};


int numVertices = 5;


List<Integer> result = topologicalSortKahn(edges, numVertices);


System.out.println("拓扑排序结果:" + result);


}


}


3.2 DFS算法实现

java

import java.util.;

public class TopologicalSortDFS {


private static List<Integer> result = new ArrayList<>();


private static boolean[] visited;

public static List<Integer> topologicalSortDFS(int[][] edges, int numVertices) {


visited = new boolean[numVertices];

for (int i = 0; i < numVertices; i++) {


if (!visited[i]) {


dfs(i, edges);


}


}

Collections.reverse(result);


return result;


}

private static void dfs(int vertex, int[][] edges) {


visited[vertex] = true;

for (int[] edge : edges) {


if (edge[0] == vertex) {


if (!visited[edge[1]]) {


dfs(edge[1], edges);


}


}


}

result.add(vertex);


}

public static void main(String[] args) {


int[][] edges = {{0, 1}, {1, 2}, {2, 3}, {3, 4}};


int numVertices = 5;


List<Integer> result = topologicalSortDFS(edges, numVertices);


System.out.println("拓扑排序结果:" + result);


}


}


4. 总结

本文介绍了有向无环图的拓扑排序,并分别使用Kahn算法和DFS算法在Java中实现了拓扑排序。通过本文的学习,读者可以了解到拓扑排序的基本概念、算法原理以及Java实现方法。在实际应用中,拓扑排序可以帮助我们更好地处理具有依赖关系的任务,提高任务调度的效率。