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

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

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

由于路径压缩在有些题目会损失海量的信息,用暴力并查集又要超时,所以就出现了启发式合并算法。

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

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

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

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

图论算法----并查集中的启发式合并_第1张图片

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

图论算法----并查集中的启发式合并_第2张图片

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

图论算法----并查集中的启发式合并_第3张图片

好了,启发式合并的原理讲得差不多了,可以发代码了,记住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]
配套一个find()函数:

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



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

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

原因很简单,因为有了路径压缩,启发式合并算法就没有保护数据的效果了。

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

你可能感兴趣的:(C++,图论,数据结构,C++图论算法详解)