图论算法----并查集中的启发式合并

来源:互联网 发布:交通意外事故数据 编辑:程序博客网 时间:2024/06/05 00:19

一、启发式合并的算法原理

一听这名字,感觉好高大上,实际上很简单。

之前讲过并查集的大部分时间都浪费在了find()函数上,于是就对find()函数进行了优化,其实还有一种算法可以使find()函数的时间复杂度控制在O(logn)左右,这种算法就是启发式合并。

并查集是一种树型的数据结构,而树也有它的深度,如果我们把一棵深度大的树的根节点接在了一棵深度小的树上,那么整棵树的深度为那一棵深度大的树的深度+1,如果我们把一棵深度小的树的根节点接在了一棵深度大的树上,则整棵树的深度为max(深度小的树的深度+1,深度大的树的深度)。这就是启发式合并的原理。

如果感觉很难理解,看下面的图就知道了。

1、有两棵树,一棵高度为3,一棵高度为5。


2、如果是普通的合并,就会造成高度为6的树。


3、如果是启发式合并,最后的树的的高度为5。


好了,启发式合并的原理讲得差不多了,可以发代码了,记住height[]数组初始化为1。


二、启发式合并的代码

void qfsunion(int x,int y){    int a=find(x);    int b=find(y);    if(height[a]>height[b])        fa[b]=a;    else if(height[a]<height[b])        fa[a]=b;    else{        fa[a]=b;        height[b]++;    }}
配套一个find()函数:

int find(x){     while(fa[x]!=0)         x=fa[x];      return x;}



三、启发式合并与路径压缩之间的问题

这时有人会问了:为什么find()函数不用路径压缩呢?

原因很简单,因为有了路径压缩,启发式合并算法就没有多大效果了。

看下面的一组图:

1、被路径压缩后的两棵树:


2、经过启发式合并:


3、又被路径压缩:


可以看出,启发式合并+路径压缩并不是最好的选择,而且路径压缩在主动改变树的高度,但是height数组的值不能同步改变,有可能让启发式合并出错。

所以启发式合并不能与路径压缩同时使用。

1 0
原创粉丝点击