Kruskal 算法复杂度分析问题

来源:8-6 Krusk算法

Poplar_hills

2019-03-13

Hi bobo 老师,

本节最后说 “Kruskal 算法的总体复杂度是 O(ElogE),其中对边进行排序的复杂度是 O(ElogE),从堆中取出边判断是否成环的复杂度是 O(ElogV)”。

不太明白“从堆中取出边判断是否成环”这个过程为什么是 O(ElogV) 的?这部分代码如下:

// 创建一个并查集, 来查看已经访问的节点的联通情况
UnionFind uf = new UnionFind(graph.V());
while( !pq.isEmpty() && mst.size() < graph.V() - 1 ){

    // 从最小堆中依次从小到大取出所有的边
    Edge<Weight> e = pq.extractMin();
    // 如果该边的两个端点是联通的, 说明加入这条边将产生环, 扔掉这条边
    if( uf.isConnected( e.v() , e.w() ) )
        continue;

    // 否则, 将这条边添加进最小生成树, 同时标记边的两个端点联通
    mst.add( e );
    uf.unionElements( e.v() , e.w() );
}

我的理解是:

  • extractMin 本身的复杂度应该是 O(logE),因为 while 循环执行了 graph.V() - 1 次,因此 graph.V() - 1 次 extractMin 就是 O(VlogE) 的复杂度。
  • 带有路径压缩优化的并查集的复杂度接近 O(1),那么 graph.V() - 1 次 isConnected 和 unionElements 就是 O(V) 的复杂度。
  • 因此这部分代码总体复杂度应该是 O(VlogE) 。

不知道哪里分析的有问题?

写回答

1回答

liuyubobobo

2019-03-13

因为这个while循环最多会循环E次,即把pq从满,到取空。


这里要注意,我们初始化pq,是将所有的边都放在了pq中,所以pq中的元素个数是E,而不是V:)


你的其他分析都是对的:)


继续加油!:)

0
4
tobeabee
回复
liuyubobobo
谢谢老师!
2021-11-23
共4条回复

算法与数据结构(C++版) 面试/评级的算法复习技能包

课程专为:短时间内应对面试、升职测评等艰巨任务打造

11187 学习 · 1614 问题

查看课程