Kruskal算法求最小生成树

来源:互联网 发布:unity3d免费模型 编辑:程序博客网 时间:2024/05/17 02:10

1.Kruskal的思想是:

先把n个顶点分成n个单独的连通分量,把边用堆排序或者别的排序排成非递减序列;

依次从中拿出最小的边,判断是不是连接两个不同的连通分量,若是,则该边是一个最小生成树的边,否则往下找次小的边,继续,直至找到n-1条边为止。

难点怎么判断一条边是不是连接两个不同的连通分量,在网上看了一些资料,大多是用并查集来实现。

具体为:

(1)维持一个father【】数组,初始化为:

for(int i = 0; i < edgenum; i++)

{

   father[i] = i;

}

(2)来一条边(u,v),在father数组中找到u和v的父亲,找父亲的函数为:

int FindFather(int x)

{

    while(father[i] != i)

   {

           i = father[i];

  }

}

看u和v的父亲是否相同,若相同则舍弃该边,不同则输出该边为最小生成树的边,然后再把u所在的连通分量和v所在的连通分量合并起来。

(3)合并函数只用了两个小数据集验证了)为:

void mergearray(int x,int y)

{

   找到x的父亲,找到y的父亲,取其中较小的父亲作为合并后的集合的父亲。

   若较小的父亲为x的父亲f1;则用

   while(father[y] != y)

   {

      y = father[y];

      father[y] = f1;//即把y的当前父亲改成合并后的集合的父亲。

   }

}

解决了判断一条边是否是连接两个不同分量的问题,剩下的主要问题就是排序了,我用的是堆排序,规模为e,排序时间为O(eloge);

下边判断边的时间为:O(e)

所以Kruskal算法的时间复杂度为:O(eloge).所以Kruskal算法适用于边少的稀疏图。

下边是代码:

test.txt的内容为:

6 10
0 1 6
0 2 1
0 3 5
1 2 5
1 4 3
2 3 5
2 4 6
2 5 4
3 5 2
4 5 6

输出结果为:


1 0
原创粉丝点击