union-find中(quick-union)算法

声明:
主要代码和部分算法说明参考自算法(第四版),这里将代码列出,是想和大家交流一些学习心得。

1.前言

鉴于quick-find需要在union方法中遍历整个数组,这样当数据庞大时,效率会非常低下,所以我们需要换一种思路,改良union方法。
注:quick-find算法请参考我的上一篇文章
http://blog.csdn.net/qq_32293345/article/details/78820208

2.思路

在quick-find算法中,id数组中存储的是每个触点的分量值,而且在同一连通分量的内部,各个触点有着相同的分量值。
但是在quick-union算法中,我们将用id数组把触点组织成一种树的关系。每一个连通分量就是一棵树。而id数组存储的为每个触点的父节点。
树根作为每个连通分量的标识。
判别两个触点是否在同一连通分量的依据:他们的树根是否相同。

3.特点

有此可见,quick-union相对于quick-find最大的优点是,在quick-find中,如果两个连通分量实现了连接,那么我们为了在数组中找出某个连通分量下的所有触点,我们需要遍历整个数组,但是对于quick-union来说就简单得多了,我们只需要一步,那就是把某一连通分量的根并入到另一棵数中就可以了。

4.代码实现

相对于quick-find我们只需要在它基础上更改两个方法即可。
4.1更改find(int p)
find方法作用:
找到该触点的根,即该触点所在连通分量的标识。

    //找出分量名称(即找到该触点的根)
    public int find(int p){
        while(p != id[p]) p = id[p]; 
        return p;
    }

我们可以知道,作为根的触点,它在数组中的值,一定是它自己本身,例如:数字1作为根,那么id[1] = 1。因为不要忘了,数组中的值表示的就是该触点的父节点。而作为根它的父节点我们可以看成它本身。
但是非根的触点,他的数组值就不一定是它本身了。

while(p != id[p]) p = id[p];

此段代码的含义:
如果触点p的值不是它的数组值,那么就将该触点的父节点赋给p,则现在触点p就变成了它的父节点了,如此递归下去,最后的p一定是根。
4.2更改union方法(int p,int q)
union方法作用:
用于将以p为根的树并入到q中(反之亦可,你开心就好)
代码:

    //将p和q的根节点统一
    public void union(int p,int q){
        int pRoot = find(p); //找到p触点的根
        int qRoot = find(q); //找到q触点的根
        if(pRoot == qRoot) return; //两根相等结束函数
        id[pRoot] = qRoot; //让树p(包括其子树)并入到以q为跟的树中
        count--; //连通分量的数量减1
    }

代码解释:

        if(pRoot == qRoot) return; //两根相等结束函数
        id[pRoot] = qRoot; //让树p(包括其子树)并入到以q为跟的树中

上面的代码标识如果两触点的根相同(二者在同一连通分量内),则结束函数。不相同话,则将以p为根的树并入到以q为根的树中。
注:并入后以p为根的树的直接父节点是q。

5.测试步骤

把文件tinyUF.txt作为main方法的参数输入。
原始数组:0 1 2 3 4 5 6 7 8 9
原始触点:
这里写图片描述

p:4 q:3
数组变为:0 1 2 3 3 5 6 7 8 9
触点图:
这里写图片描述
说明:根据find算法首先判断出4的根为id[4]=4,3的根为id[3]=3。然后在union中判断出二者的根不相同,然后将根为4的树并入到3下。

p:3 q:8
数组变为:0 1 2 8 3 5 6 7 8 9
触点图:
这里写图片描述

p:6 q:5
数组变为:0 1 2 8 3 5 5 7 8 9
触点图:
这里写图片描述

p:9 q:4
数组变为:0 1 2 8 3 5 5 7 8 8
触点图:
这里写图片描述
这里面需要注意的是,触点9应该加到树根8的下面,而不是节点4的下面,因为9需要和4的根8进行比较。

p:2 q:1
数组变为:0 1 1 8 3 5 5 7 8 8
触点图:
这里写图片描述

p:8 q:9
数组变为:0 1 1 8 3 5 5 7 8 8
触点图:没有变化

p:5 q:0
数组变为:0 1 1 8 3 0 5 7 8 8
触点图:
这里写图片描述

p:7 q:2
数组变为:0 1 1 8 3 0 5 1 8 8
触点图:
这里写图片描述

p:6 q:1
数组变为:1 1 1 8 3 0 5 1 8 8
触点图:
这里写图片描述

p:1 q:0
数组变为:1 1 1 8 3 0 5 1 8 8
触点图:无变化

p:6 q:7
数组变为:1 1 1 8 3 0 5 1 8 8
触点图:无变化

猜你喜欢

转载自blog.csdn.net/qq_32293345/article/details/78825280