不相交集

不相交集用来解决等价问题,特点是编程实现很简单但是分析复杂。

关系:对于每一对元素(a,b),a,b\in SaRb或者为true或者为false,称在集合S上定义关系R。若aRb是true,那么a和b有关系

等价关系:是满足以下3个性质的关系R:

1.自反性,对所有a\in S,aRa

2.对称性,aRb当且仅当bRa

3.传递性,若aRb,bRc,那么aRc

一个例子:\leqslant不是等价关系,满足自反性和传递性,但是不满足对称性

用来解决等价问题的数据结构:

1.使用二维数组,缺点是浪费大量空间,比如若定义~是等价关系,那么a~b,b~c,c~d就足够判断abcd4个元素是相互等价的,但是二维布尔数组来表示这个问题很不明显

2.使用等价类,一个元素a\in S的等价类是S的一个子集,包含所有和a有关系的元素,注意,每个元素只能出现在一个等价类中,否则按照传递性,两个等价类将合并。这样,为了验证a~b,只要验证a和b是否在一个等价类中。等价类的数据结构描述:初始输入是N个集合的类,每个集合中只有一个元素,集合之间不相交,允许使用两种运算:

Find:返回给定元素的集合的名字

Union:将a和b所在的两个等价类合并成一个新的等价类

称为不相交集的find/union运算,这是一个联机算法,执行过程中,集合通过union改变

方案:解决动态等价问题有两种方案,一种保证find常数时间,一种保证union常数时间,这两者不能同时做到。

代码如下:

#include <stdio.h>

#define NumSets   128

typedef int DisjSet[NumSets + 1];
typedef int SetType;
typedef int ElementType;

void Initialize(DisjSet S);
void SetUnion(DisjSet S, SetType Root1, SetType Root2);
SetType Find(ElementType X, DisjSet S);

/* 隐式的树,值为0表示自己是根,初始的时候,每个元素都是根 */
void Initialize(DisjSet S)
{
    int i;

    for (i = NumSets; i > 0; i--)
        S[i] = 0;
}

/* 合并,将Root2的根设置为Root1 */
void SetUnion(DisjSet S, SetType Root1, SetType Root2)
{
    S[Root2] = Root1;
}

/* 查找根,递归直到值为0,就找到了一个根,返回在数组中的位置 */
SetType Find(ElementType X, DisjSet S)
{
    if (S[X] <= 0)
        return X;
    else
        return Find(S[X], S);
}

两种灵巧求并的改进:

1.按大小求并

上面的代码中,union操作是无条件的,可以按大小求并,每次将小的合并到大的上,这样,深度最多是logN,因为每次合并都被放到至少是原来节点2倍的树中,一共可以合并logN次,也就是说find操作的时间是logN,M次find操作的时间是O(MlogN),最坏情况就是二项队列中的二项树。改进方法是,原来数组中值为0表示是根,改成节点个数的负值,初始时所有节点都是-1,后续union的时候,根所在节点的负值增加

2.按高度求并

和按大小求并类似,也保证深度最多O(logN),按高度求并代码如下

void SetUnion(DisjSet S, SetType Root1, SetType Root2)
{
    /* 若Root2更深,那么将Root1合并到Root2上 */
    if (S[Root2] < S[Root1])
        S[Root1] = S[Root2];
    else
    {
        /* 若高度相等,那么增加高度 */
        if (S[Root1] == S[Root2])
            S[Root1]--;
        S[Root2] = Root1;
    }
}

路径压缩:对于连续M次操作,平均时间是O(M),但是最坏的O(MlogN)时间会发生,比如union之后形成了一个二项树。对union无法改进,因为无论按照何种方法执行union,都会造出来一个相同的最坏情形的树,也就是二项树,改进find如下:每次find(X)之后,从X到根的每个节点都让它的父节点变成根,只要对代码进行一点改进就可以实现,如下:

SetType Find(ElementType X, DisjSet S)
{
    if (S[X] <= 0)
        return X;
    else
        return S[X] = Find(S[X], S);
}

路径压缩和按照大小求并完成兼容,但是和按高度求并不兼容,因为会修改树的高度,但是可以使用秩,作为估计的高度

按秩求并和路径压缩的最坏情形:使用这两种方法,算法在最坏情形下几乎是线性的,精确时间是\Theta (M\alpha (M,N)),M\geqslant N,其中,\alpha(M,N)是Ackermann函数的逆,Ackermann函数如下定义:

A(1,j)=2^j,j\geqslant 1

A(i,1)=A(i-1,2),i\geqslant 2

A(i,j)=A(i-1,A(i,j-1)),i,j\geqslant 2

由此定义\alpha (M,N)=min\left \{ i\geqslant 1|A(i,\left \lfloor M/N \right \rfloor)> logN \right \},在实际应用中,\alpha(M,N)\leqslant 4。单变量反Ackermann函数写成log^{*}N,是N的直到N\leqslant 1的取对数的次数,log^{*}65535= 4log^{*}2^{65536}= 5\alpha(M,N)增长的比log^{*}N还慢,不过不是常数,导致时间不是线性的

结论:使用路径压缩和按秩求并,任意顺序的M=\Omega (N)次Union/Find操作花费的时间是O(Mlog^{*}N)

分析:Union和Find操作可以以任何顺序出现,Union按秩进行,Find使用路径压缩

引理1:执行一系列Union指令时,一个秩为r的节点必然至少有2^{r}个后裔,包括自己

证明:数学归纳法

引理2:秩为r的节点的个数最多是N/2^{r}

证明:秩为r的节点至少有2^{r}个子节点,一共N个节点,所以得到这个个数

引理3:在Union/Find算法的任一时刻,从树叶到根的路径上的节点的秩单调增加

证明:显然

记账法则:对于从代表i的定点到根的路径上的所有顶点v,在两个账户之一存入一个分币:

法则1.若v是根,或者v的父亲是根,或者v的父亲和v在不同的秩组中,那么将一个美分存入公共储金

法则2.否则,将一个canada分币存入该顶点中

引理4:对任意的find(v),无论存入总储金还是存入顶点,所存分币总数恰好等于从v到根的路径上的节点数

证明:显然

引理5:经过整个算法,在法则1下美分存入的总的数量是M(G(N)+2)

证明:对于任意find,有根和根的儿子,有2个,由于一个路径上节点的秩单调递增,一共G(N)个秩组,因此一共还可以放G(N)个,M次find总的数量就是M(G(N)+2)

引理6:秩组g > 0中顶点的个数V(g)至多为N/2^{F(g-1)}

证明:由引理2,至多存在N/2^{r}个秩为r的节点,对秩组g中的秩求和,得到

V(g)\leqslant \sum_{r=F(g-1)+1}^{F(g)}\frac{N}{2^{r}}

          \leqslant \sum_{r=F(g-1)+1}^{\infty }\frac{N}{2^{r}}

          \leqslant N\sum_{r=F(g-1)+1}^{\infty }\frac{1}{2^{r}}

          \leqslant \frac{N}{2^{F(g-1)+1}}\sum_{s=0}^{\infty }\frac{1}{2^{s}}

          \leqslant \frac{2N}{2^{F(g-1)+1}}

          \leqslant \frac{N}{2^{F(g-1)}}

引理7:存入秩组g的所有顶点的canada分币的最大的个数至多是NF(g)/2^{F(g-1)}

证明:秩组g中有F(g)-F(g-1)个节点,应用引理6得到结果

引理8:在法则2下存入分币最多是N\sum_{g=1}^{G(N)}F(g)/2^{F(g-1)}个canada分币

证明:显然

综上,法则1和法则2总的分币数是M(G(N)+2)+N\sum_{g=1}^{G(N)}F(g)/2^{F(g-1)}

定理:M次Union和Find的运行时间是O(Mlog^{*}N)

证明:F是F(0) = 0F(i)=2^{F(i-1)}递归定义的函数,G(N)=1+\left \lfloor log^{*}N \right \rfloor,将F和G定义插入到引理8中,得到结论

猜你喜欢

转载自blog.csdn.net/kdb_viewer/article/details/83011406