引言
拓扑排序是有向无环图(DAG)中的一种线性排序,使得对于图中的每一条有向边 ( u \rightarrow v ),顶点 ( u ) 在排序中出现在顶点 ( v ) 之前。本文将详细介绍两种实现拓扑排序的算法:Kahn算法和基于深度优先搜索(DFS)的算法。
目录
Kahn算法
定义
Kahn算法是一种基于入度的拓扑排序算法。该算法通过不断移除入度为0的顶点及其边来构建拓扑排序。
算法步骤
- 初始化:计算图中所有顶点的入度,并将所有入度为0的顶点添加到一个队列中。
- 构建排序:从队列中取出一个顶点,将其添加到拓扑排序的结果中,并移除该顶点及其所有出边。对于每个被移除的出边,如果目标顶点的入度减为0,则将该顶点添加到队列中。
- 检测环:重复步骤2,直到队列为空。如果排序结果中的顶点数量小于图中的顶点数量,则说明图中存在环,无法进行拓扑排序。
示例
假设我们有一个有向无环图,顶点集合为 ({A, B, C, D, E, F}),边集合为 ({(A, C), (B, C), (B, D), (C, E), (D, F), (E, F)})。
Kahn算法实现
下面是用Java实现Kahn算法的代码示例:
import java.util.*;
public class KahnAlgorithm {
private int vertices; // 顶点数量
private List<Integer>[] adjList; // 邻接表
public KahnAlgorithm(int vertices) {
this.vertices = vertices;
adjList = new List[vertices];
for (int i = 0; i < vertices; i++) {
adjList[i] = new ArrayList<>();
}
}
// 添加边
public void addEdge(int src, int dest) {
adjList[src].add(dest);
}
// Kahn算法实现的拓扑排序
public void topologicalSort() {
int[] inDegree = new int[vertices];
for (int i = 0; i < vertices; i++) {
for (int dest : adjList[i]) {
inDegree[dest]++;
}
}
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < vertices; i++) {
if (inDegree[i] == 0) {
queue.add(i);
}
}
List<Integer> topOrder = new ArrayList<>();
while (!queue.isEmpty()) {
int u = queue.poll();
topOrder.add(u);
for (int neighbor : adjList[u]) {
if (--inDegree[neighbor] == 0) {
queue.add(neighbor);
}
}
}
if (topOrder.size() != vertices) {
System.out.println("图中存在环,无法进行拓扑排序");
return;
}
System.out.println("拓扑排序结果:");
for (int node : topOrder) {
System.out.print(node + " ");
}
}
public static void main(String[] args) {
KahnAlgorithm graph = new KahnAlgorithm(6);
graph.addEdge(0, 2);
graph.addEdge(1, 2);
graph.addEdge(1, 3);
graph.addEdge(2, 4);
graph.addEdge(3, 5);
graph.addEdge(4, 5);
graph.topologicalSort();
}
}
代码注释
-
类和构造函数:
public class KahnAlgorithm { private int vertices; // 顶点数量 private List<Integer>[] adjList; // 邻接表 public KahnAlgorithm(int vertices) { this.vertices = vertices; adjList = new List[vertices]; for (int i = 0; i < vertices; i++) { adjList[i] = new ArrayList<>(