繁体   English   中英

关于 Kahn 的 BFS 算法中用于拓扑排序的时间复杂度的问题

[英]Issue regarding time complexity in Kahn's BFS algo for topological sort

到处都写着用于拓扑排序的 Kahn 的 BFS 算法需要 O(V+E) 时间复杂度,但是如果我分解它的代码,我意识到在计算顶点的入度时,我们正在多次访问一个顶点,所以不应该TC 是 O(n^2) 吗? 同样在我们的 while 循环中,我们不止一次访问顶点,那么 TC 怎么仍然是 O(V+E) ?

这是我的代码:

public static void sort(ArrayList<ArrayList<Integer>> adjList,int vertices){
        int[] inDegree=new int[vertices];
        for(int i=0;i<adjList.size();i++){
            for(int element : adjList.get(i)){
                inDegree[element]++;
            }
        }
        Queue<Integer> ourQueue=new LinkedList<>();
        for(int i=0;i<vertices;i++){
            if(inDegree[i]==0){
                ourQueue.add(i);
            }
        }
        while(!ourQueue.isEmpty()){
            int poppedElement=ourQueue.poll();
            System.out.print(poppedElement+" ");
            for(int element : adjList.get(poppedElement)){
                inDegree[element]--;
                if(inDegree[element]==0){
                    ourQueue.add(element);
                }
            }
        }
    }

在大多数图表中, |E| >> |V| . 让我们使用|E| = m |E| = m|V| = n |V| = n 在连通图中,您将拥有m >= n-1 在完整的图表中,您将拥有m = n*(n-1) 因此,对于m介于这些极端之间的“平均”图, O(m+n)看起来与O(m)O(n*n)非常相似。

在您的实现中,您使用的是具有n*n单元的邻接矩阵; 简单地填充该矩阵已经是O(n*n) - 在第一个循环中执行的顶点度数计算也是如此。 如果您使用的是邻接列表,则不需要循环(顶点度数可以计算为每个顶点的邻接列表的长度,如果使用 ArrayList ,则为 O(1))。 因此,实现肯定会影响运行时最坏情况的复杂性。

您评论说,一个在线编程拼图网站将您的代码列为O(V+E) 然而,找出一段代码复杂性的唯一实用方法(没有人工或非常复杂的自动分析,在一般情况下注定会失败)是用一组不断增加的输入来运行它。 正如我在上面所说的, O(V+E)O(V*V)之间的差异可能相对较小。

简而言之:

  • 用于算法的确切图形表示会极大地影响其运行时复杂度。 对稀疏图使用邻接列表以节省时间和内存。
  • 在稠密图中, m接近n*n ,并且O(V+E)O(E)O(V*V)之间没有显着差异
  • 在线编程测验无法准确确定最坏情况下的运行时复杂度。 他们可以给你一个估计,但这只是一个经验猜测,而不是基本事实。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM