Disjoint-set (disjoint sets) Detailed Implementation and java

@ (Article directories)

Understanding disjoint-set

For 并查集(不相交集合)a lot of people will feel very 陌生, heard or not particularly aware of . Indeed disjoint-set is a very efficient data structure. Simple , but all the elements of the system 一遵从一个规律so efficient and let them do things efficiently.

For certain sense, such a definition on Wikipedia:

Disjoint-set, a set of applications in a number of issues have N elements, we usually make at the beginning of each element of the collection constitute a single element , then a certain order will belong to the set of elements of the same consolidated group where , during to repeatedly to find an element in which the collection. It features does not seem complicated, but the amount of data is great, if your normal data structure to describe it, often in the space is too large, the computer can not afford; even in the space of barely passed, the time complexity of the operation is also very high, impossible to describe the results of calculating the desired questions, and can only be used to check the game sets a predetermined operation time of (1 to 3 seconds).

It is a disjoint-set 树型的数据结构for dealing with some disjoint sets (Disjoint Sets) mergers and inquiries . Often use to forest to represent.

And check assembly resolution

The basic idea

  • Initialization , a forest each as an independent. Usually represented by an array, each initial value of -1.各自为根
    Here Insert Picture Description
  • join(a,b)operating. a, b two 集合combined. Note here is a, not a, b merge, but merge the set of a, b's. This spawns some cases:
  • a, b if it is a separate (and no other consolidated) , then directly to a point b (point a or b), namely data[a]=b; this set in order to express the number of original -1. Again -1 i.e., b data[b]=-2. b is expressed in father node has | -2 | months.
    Here Insert Picture Description
    Here Insert Picture Description
  • a, b if there is a set of (possibly his father, he is probably the root) , then we of course 不能直接操作a,b(because a, b may have been pointing to someone else.) So we can only operate a, b ancestors . Because a, b ancestors is not directed ( i.e., a negative value indicates the size of data ). So they first a negative value to be added on top of another to go. In addition to this value becomes the point of contact that represents.
    Here Insert Picture Description

For the above you may be in doubt:

How can I see a, b whether in a collection?

  • Whether viewed in a collection, just to see 节点根祖先的结果是否相同即可. Because only root value is negative , while others are positive elements representing points. So it is necessary only 一直寻找直到不为正数进行比较即可!

a, b merger, whether it is a merger of the ancestors in the ancestral b, or b ancestors on a merger?

  • Here will encounter both cases, the choice is very important. You have to understand one thing: +1 height of the tree so the efficiency of the elements of the query will be reduced!

So we usually are: a decimal point to the tree (the tree pointing to a higher or lower tree), this makes the query efficiency can be increased!
Here Insert Picture Description
Of course, the height and number on choice, you also need your own choice and consideration.

Other paths compression?

Each query, from the bottom up. When we call the recursive compression path can be the way, because we really only need to find one element until its ancestors, so when he was closer ancestor so 下次查询就很快. And the cost of compression path is not great!
Here Insert Picture Description

Code

Disjoint-set is relatively simple to implement, directly attached to the code!

package 并查集不想交集合;

import java.util.Scanner;
public class DisjointSet {
    static int tree[]=new int[100000];//假设有500个值
    public DisjointSet()    {set(this.tree);}
    public DisjointSet(int tree[]) 
    {
        this.tree=tree;
        set(this.tree);
    }
    public void set(int a[])//初始化所有都是-1 有两个好处,这样他们指向-1说明是自己,第二,-1代表当前森林有-(-1)个
    {
        int l=a.length;
        for(int i=0;i<l;i++)
        {
            a[i]=-1;
        }
    }
    public int search(int a)//返回头节点的数值
    {
        if(tree[a]>0)//说明是子节点
        {
            return tree[a]=search(tree[a]);//路径压缩
        }
        else
            return a;
    }
    public int value(int a)//返回a所在树的大小(个数)
    {
        if(tree[a]>0)
        {
            return value(tree[a]);
        }
        else
            return -tree[a];
    }
    public void union(int a,int b)//表示 a,b所在的树合并
    {
        int a1=search(a);//a根
        int b1=search(b);//b根
        if(a1==b1) {System.out.println(a+"和"+b+"已经在一棵树上");}
        else {
        if(tree[a1]<tree[b1])//这个是负数,为了简单减少计算,不在调用value函数
        {
            tree[a1]+=tree[b1];//个数相加  注意是负数相加
            tree[b1]=a1;       //b树成为a的子树,直接指向a;
        }
        else
        {
            tree[b1]+=tree[a1];//个数相加  注意是负数相加
            tree[a1]=b1;       //b树成为a的子树,直接指向a;
        }
        }
    }
    public static void main(String[] args)
    {       
        DisjointSet d=new DisjointSet();
        d.union(1,2);
        d.union(3,4);
        d.union(5,6);
        d.union(1,6);
        
        d.union(22,24);
        d.union(3,26);
        d.union(36,24);
        System.out.println(d.search(6));    //头
        System.out.println(d.value(6));     //大小
        System.out.println(d.search(22));   //头
        System.out.println(d.value(22));     //大小
    }
}

Here Insert Picture Description

Epilogue

  • Disjoint-set are simple but very efficient data structure. In the often encountered in the collection . If you do not use disjoint-set while the traditional efficiency violence is too low, without being adopted.
  • In addition, 并查集还广泛用于迷宫游戏the following have the opportunity to introduce a disjoint-set to achieve a maze game . We welcome attention!
  • Finally, I welcome everyone's attention the public number, learn together, exchange! 笔者学习资源Also placed in the public numbers and share with everyone!

Guess you like

Origin www.cnblogs.com/bigsai/p/11423380.html