【拓扑排序】两种拓扑排序算法

本文深入探讨了拓扑排序的概念,并详细介绍了两种常见的拓扑排序算法:深度优先搜索(DFS)和广度优先搜索(BFS)。通过实例解析,阐述了这两种方法的步骤与区别,帮助读者理解如何在有向无环图(DAG)中有效地进行节点排序。
public class Graph {

    /**
     * 节点数量
     */
    public int v;
    public LinkedList<Integer> adj[];

    private Graph(int v) {
        this.v = v;
        // 初始化顶点
        adj = new LinkedList[v];
        for (int i = 0; i < v; i++) {
            adj[i] = new LinkedList<>();
        }
    }

    /**
     * 添加边
     * @param i
     * @param j
     */
    private void addEdge(int i, int j) {
        adj[i].add(j);

    }

}
public class TopoSort {

    /**
     *
     * @param graph
     */
    private static void topoSort(Graph graph, int v) {
        // 辅助作用
        LinkedList<Integer> queue = new LinkedList<>();
        int[] result = new int[v];

        // 每个节点的入度
        int[] degree = new int[v];
        for (int i = 0; i < v; i++) {
            for (int j = 0; j < graph.adj[i].size(); j++) {
                int w = graph.adj[i].get(j);
                degree[w]++;
            }
        }
        // 把入度为0的加入队列中
        for (int i = 0; i < v; i++) {
            if (degree[i] == 0) {
                queue.add(degree[i]);
                break;
            }
        }

        // 开始逐个处理
        int currentIndex = 0;
        while (!queue.isEmpty()) {
            int node = queue.remove();
            result[currentIndex++] = node;
            // 获取此节点的出边
            LinkedList<Integer> edges = graph.adj[node];
            for (int j = 0; j < edges.size(); j++) {
                int w = edges.get(j);
                degree[w]--;
                if (degree[w] == 0) {
                    queue.add(degree[w]);
                }
            }
        }

    }

    private static void topoSortByDFS(Graph graph, int v) {
        // 首先简历逆序表
        LinkedList<Integer>[] reseveEdges = new LinkedList[v];
        // 初始化
        for (int i = 0; i < v; i++) {
            reseveEdges[i] = new LinkedList<>();
        }
        for (int i = 0; i < v; i++) {
            for (int j = 0; j < graph.adj[i].size(); j++) {
                int w = graph.adj[i].get(j);
                reseveEdges[w].add(i);
            }
        }
        // 逆序表简历完成,创建节点的访问情况
        boolean[] visible = new boolean[v];

        for (int i = 0; i < v; i++) {
            // 逐个节点进行遍历
            if (!visible[i]) {
                visible[i] = true;
                travelDFS(i, reseveEdges, visible);
            }
        }

    }

    private static void travelDFS(int v, LinkedList<Integer>[] reseveEdges, boolean[] visit) {
        // 访问的时候先访问入度的节点,再访问自身
        LinkedList<Integer> lastNodes = reseveEdges[v];
        for (int i = 0; i < lastNodes.size(); i++) {
            int w = lastNodes.get(i);
            if (visit[w]) {
                continue;
            }
            // 否则访问夫节点
            travelDFS(w, reseveEdges, visit);
        }
        Log.d("zpb", "-->" + v);

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值