并查集

并查集是集合的一种,它只有两种方法,合并和查找。

合并就是把两个元素所在的集合合并为一个。

查找就是查找某元素所属的集合。

一般并查集用树的父指针数组来存储实现。根节点数组值为负数,负几表示该集合有几个元素。

元素和集合名称对应数组索引。从属关系对应相应数组值。数组值为负数,表示对应索引为树的根,也就是集合名。

初始状态下所有元素都是一颗单独的树,也就是说所有数组值都初始化为-1.

某种意义上并查集的数组实现也可看成一种散列。

由于并查集只有两种操作,所以重要的不是元素之间的父子关系,而是元素的从属关系。

所以最优并查树的深度应为2。一般优化并查树,也是往这个方向优化。

并查树合并O(1), 查找O(logn)。

并查集是划分等价类的最佳选择。

下面给出代码实现:

package com.company;

/**
 * UnionFindSet is a set to tackle only Union and Find operations in set.
 * Created by qiguo on 2017/3/21.
 */
public class MyUnionFindSet {
    private int[] array;
    private int storageSize;
    public MyUnionFindSet(){
        this.storageSize = 10;
        this.array = new int[this.storageSize];
        for (int i = 0; i < this.storageSize; i++) {
            array[i] = -1;
        }
    }

    /**
     * merge two element into one set
     * @param s1 element s1
     * @param s2 element s2
     * @return union set element num
     */
    public int union(int s1, int s2){
        int set1 = find(s1);
        int set2 = find(s2);
        if (set1 == set2){
            return -1;
        }
        if (array[set1] <= array[set2]){
            array[set1] += array[set2];
            array[set2] = set1;
            return array[set1];
        }else {
            array[set2] += array[set1];
            array[set1] = set2;
            return array[set2];
        }
    }

    /**
     * find the set that element belongs to
     * @param element
     * @return set number
     */
    public int find(int element){
        int tmp = element;
        while (array[tmp] > 0){
            tmp = array[tmp];
        }
        return tmp;
    }

    /**
     * collapse the branch while find, to optimize the structure of the tree.
     * @param element
     * @return the set number that element belongs to
     */
    public int collapsingFind(int element){
        int tmp = element;
        while (array[tmp] > 0){
            tmp = array[tmp];
        }
        while (array[element] > 0){
            int parent = array[element];
            array[element] = tmp;
            element = parent;
        }
        return tmp;
    }

    public void print(){
        for (int element: array) {
            System.out.printf(element + " ");
        }
        System.out.println();
    }
    public static void main(String[] args){
        MyUnionFindSet myUnionFindSet = new MyUnionFindSet();
        myUnionFindSet.union(1,2);
        myUnionFindSet.union(2,3);
        myUnionFindSet.union(1,5);
        myUnionFindSet.union(4,6);
        myUnionFindSet.union(7,9);
        myUnionFindSet.union(1,6);
        myUnionFindSet.union(1,6);
        myUnionFindSet.print();
        myUnionFindSet.collapsingFind(6);
        myUnionFindSet.print();
        System.out.println(myUnionFindSet.find(6));
        System.out.println(myUnionFindSet.find(1));
    }


}

  

原文地址:https://www.cnblogs.com/zqiguoshang/p/6593245.html