路径压缩优化并查集大家一定很熟练了,那么它的复杂度是多少呢?
O(mα(n))?
的确,很多人都是这么说的,但是事实上它的复杂度是
O(mlog1+m/nn)的,并且能找到一种方法卡到这样的复杂度。
要卡并查集,首先要构造一种树——二项树。这种二项树还与普通的不太一样。
定义:在给定
j的情况下,二项树
Tk定义如下:
- 若
k≤j,
Tk是一个点。
- 若
k>j,
Tk是
Tk−1的根结点增加一棵
Tk−j的子树。

这棵树非常有意思,我们可以展开
Tk−j,接着展开
Tk−2j……
另外,也可以展开
Tk−1,接着展开
Tk−2……

容易发现,图5看起来像图4的路径压缩之后的结果,但是不完全一样。
如果首先按照图5的方式展开
j棵子树,再按图4展开,可以得到

此时,如果在根节点上再加一个点,
j次访问
T1到
Tj,那么路径压缩后可以得到图5外加一个点作为根的儿子。
也就是说,这棵二项树路径压缩后约等于没有路径压缩……只是将原来作为根结点父亲的那个点变成了儿子。
至于
Tk的点数,通过数学归纳法可以发现不会超过
(j+1)k/j−1个。
假设
m≥n,令
j=nm,i=logj+12n+1,k=ij,那么
Tk的点数不超过
2n。接下来做
2n组操作,每次加入一个点作为根结点的父亲,然后对
T1到
Tj逐个查询,每次查询的长度是
i+1,同时查询的次数显然不超过
m。因此总操作次数为
2nj(i+1),即
O(mlog1+m/nn)。
图片取自康复计划#4 快速构造支配树的Lengauer-Tarjan算法。