拓扑排序:Kahn算法与DFS算法

引言

拓扑排序是有向无环图(DAG)中的一种线性排序,使得对于图中的每一条有向边 ( u \rightarrow v ),顶点 ( u ) 在排序中出现在顶点 ( v ) 之前。本文将详细介绍两种实现拓扑排序的算法:Kahn算法和基于深度优先搜索(DFS)的算法。

目录

  1. Kahn算法
  2. 基于DFS的算法

Kahn算法

定义

Kahn算法是一种基于入度的拓扑排序算法。该算法通过不断移除入度为0的顶点及其边来构建拓扑排序。

算法步骤

  1. 初始化:计算图中所有顶点的入度,并将所有入度为0的顶点添加到一个队列中。
  2. 构建排序:从队列中取出一个顶点,将其添加到拓扑排序的结果中,并移除该顶点及其所有出边。对于每个被移除的出边,如果目标顶点的入度减为0,则将该顶点添加到队列中。
  3. 检测环:重复步骤2,直到队列为空。如果排序结果中的顶点数量小于图中的顶点数量,则说明图中存在环,无法进行拓扑排序。

示例

假设我们有一个有向无环图,顶点集合为 ({A, B, C, D, E, F}),边集合为 ({(A, C), (B, C), (B, D), (C, E), (D, F), (E, F)})。

A
C
B
D
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();
    }
}

代码注释

  1. 类和构造函数

    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<>(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

捕风捉你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值