union-find算法解析(并查集)

本文主要学习了《算法》(Robert Sedgewick Kevin Wayne)中关于union-find的介绍,并对所有的重要知识点进行总结。


1、定义

p、q代表单个触点,整数对(p,q)代表这两个值代表的点相连。每次输入一对(p,q)时判断两个点是否连通,如果不连通则添加连接。


2、应用

1) 大型网络中,已知一些计算机相连,判断任意两个点是否连通

2) 变量名等价性:给定两个变量,这两个变量指向同一个对象的引用,则称为等价。判断任意两个变量是否等价


3、抽象

在处理(p,q)时判断是否属于同一个集合:如果是,说明已经连通;如果不是,说明p、q未连通,则添加连接并且合并集合


4、算法变量及函数

变量:count表示分量数量;id数组表示分量所在集合id

1) int count():返回连通分量的个数,有合并操作时个数减一

2) boolean connected(p,q):返回p、q是否连通

3) int find(p):返回p所在分量标识符

4) void union(p,q):在p、q之间添加连接


5、算法实现

1) quick-find:id中的值即为分量的id,在同一个集合中的触点对应的id都相同,这样保证connected只需要判断两个触点的find返回值是否相同即可。而union函数需要保证合并集合时将id也对应修改为相同。

int find(int p){
    return id[p];
}

void union(int p, int q){
    int pID = find(p);
    int qID = find(q);

    if(pID == qID) 
        return;
    
    for(int i=0; i<id.length; i++){
        if (id[i] == pID)
            id[i] = qID;
    }
    count--;
    
}

但这样的方法union中计算量很大,需要遍历整个id数组来改变索引

2) quick-union:为了能够加快union的速度,我们只需要保证union能够使的两个需要连通的节点的根节点相同即可;而这样的话,找到分量的名称,需要找到根节点对应的分量,所以find函数需要通过循环一直找到分量。

int find(int p){
    while(p != id[p])
        p = id[p];
    return p;
}

void union(int p, int q){
    int pRoot = find(p);
    int qRoot = find(q);

    if(pRoot == qRoot)
        return;

    id[pRoot] = qRoot;
    count--;

}

上面的实现find函数中,知道找到触点在id中的分量和其本身相同时,才算作找到其根节点分量。

但是可能遇到情况:连通图是线性的,构造的树越来越深,每次find中的循环操作时间越来越长,从而使得算法效率较低。


3) 加权quick-union:这是对上一个方法的小改动,从而避免数越来越深的情况。改动就是在union的根节点改变时,将小的树挂到大的树上。所以这里需要引入另外一个变量sz数据,用来表示每一个集合的大小,初始时也是每一个初始化为1。

int find(int p){
    while(p != id[p])
        p = id[p];
    return p;
}

void union(int p, int q){
    int pRoot = find(p);
    int qRoot = find(q);

    if(pRoot== qRoot)
        return;

    if(sz[pRoot]<sz[qRoot]){
        id[pRoot]=qRoot;
        sz[qRoot] += sz[pRoot];
    } else{
        id[qRoot]=pRoot;
        sz[pRoot] += sz[qRoot];
    }
    count--;

}
3) 最优算法:我们想要保证能够在常数时间内完成find和union操作,但这样的目标是难以实现的。所以算法的进一步改进只能集中在扁平化生成的树,所以改动的地方在于:在find中添加循环,使得在路径上遇到的所有节点,都将其直接链接到根节点。这是目前为止最为优化的算法。


猜你喜欢

转载自blog.csdn.net/u010358304/article/details/79439385