有向无环图的拓扑排序

Graph Algorithm 专栏收录该内容
25 篇文章 2 订阅

有向无环图的拓扑排序

  • 有向无环图 (DAG)拓扑排序是顶点的线性排序,使得对于每个有向边 u, v,顶点 u排在 v 之前。如果图不是 DAG,则无法对图进行拓扑排序

  • 例如,下图的拓扑排序是「5 4 2 3 1 0」。一个图可以有多个拓扑排序。例如,下图的另一种拓扑排序是「4 5 2 3 1 0」。拓扑排序中的第一个顶点始终是入度为 0 的顶点(没有传入边的顶点)。

在这里插入图片描述

拓扑排序与深度优先遍历(DFS):

  • DFS,我们打印一个顶点,然后对其相邻顶点递归调用 DFS
  • 拓扑排序中,我们需要在相邻顶点之前打印一个顶点。例如,在给定的图中,顶点 ‘5’ 应该在顶点 ‘0’ 之前打印,但与DFS不同的是,顶点 ‘4’ 也应该在顶点 ‘0’ 之前打印。所以拓扑排序不同于DFS。例如,所示图的 DFS 是「5 2 3 1 0 4」,但它不是拓扑排序。

Algorithm:

  • DFS,我们从一个顶点开始,首先打印它,然后对其相邻顶点递归调用 DFS。
  • 在拓扑排序中,我们使用临时堆栈。我们不会立即打印顶点,我们首先对其所有相邻顶点递归调用拓扑排序,然后将其压入堆栈。最后,打印堆栈的内容。请注意,仅当顶点的所有相邻顶点(及其相邻顶点等)都已在堆栈中时,才会将顶点压入堆栈。

下面是是上述方法的实现过程:
请添加图片描述

Code:

   static class Graph {
        private int V;
        private List<List<Integer>> adj;

        //初始化构建图
        public Graph(int V) {
            this.V = V;
            adj = new ArrayList<>();
            for (int i = 0; i < this.V; i++) {
                adj.add(new ArrayList<>());
            }
        }

        //有向图
        public void addEdge(int u, int v) {
            adj.get(u).add(v);
        }


        public void topologicalSortUtil(int u, boolean[] vis, Stack<Integer> stk) {
            vis[u] = true;//标记当前节点被访问过
            for (int v : adj.get(u)) {
                if (!vis[v]) topologicalSortUtil(v, vis, stk);
            }
            stk.push(u);//加入当前节点
        }


        public void topologicalSort() {
            Stack<Integer> stk = new Stack<>();
            boolean[] vis = new boolean[V];
            for (int u = 0; u < V; u++) {//依次遍历
                if (!vis[u]) topologicalSortUtil(u, vis, stk);
            }
            while (!stk.isEmpty()) {
                System.out.print(stk.pop() + " ");
            }
        }

        public static void main(String args[]) {
            // Create a graph given in the above diagram
            Graph g = new Graph(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);
            System.out.println("Following is a Topological sort of the given graph");
            g.topologicalSort();
            //5 4 2 3 1 0
        }
    }

复杂度分析:

  • 时间复杂度: O(V+E)。
    上面的算法只是带有额外堆栈的 DFS。所以时间复杂度与 DFS 相同。
  • 空间复杂度: O(V)。
    堆栈需要额外的空间。

Reference

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值