Search code examples
javakruskals-algorithmunion-find

implement Union-Find Algorithm confusion


I'm trying to implement a union-find alg for Kruskal. I'm using this pseudo code, I don't understand the union part step2 below (its not a recursive call) or if I am even close. If this way doesn't work I can use any implementation as long as I understand it. Thanks ahead of time. U and V are my edge nodes, just ints for now.

  Init(V)
  1.for every vertex v do
  2.boss[v]=v
  3.size[v]=1
  4.set[v]={v}

  Find (u)
  1.Return boss[u] 

  Union (u,v)
  1.if size[boss[u]]>size[boss[v]] then
  2.set[boss[u]]=set[boss[u]] union set[boss[v]]
  3.size[boss[u]]+=size[boss[v]]
  4.for every z in set[boss[v]] do
  5.boss[z]=boss[u]
  6.else do steps 2.-5. with u,v switched

I don't understand step 2, here is my code so far:

public class UnionFind {

    private int[] _boss;
    private int[] _size;
    private int[] _set;

    public UnionFind(int max) 
    {
        _boss = new int[max];
        _size = new int[max];
        _set  = new int[max];
    }

    public void init(Set<Integer> vertSet)
    {
        //for every vertex do
        int j=0;
        for(int i : vertSet)
        {
            _boss[j]=i;
            _size[j]=1;
            _set[j]=i;
            j++;
        }
    }

    int find(int u)
    {
        return(_boss[u]);
    }

    void union(int u, int v)
    {
        if(_size[_boss[u]]>_size[_boss[v]])
        {
            _set[_boss[u]]=_set[_boss[u]];
             //_set[_boss[v]];
            _size[_boss[u]]+=_size[_boss[v]];

            for(int z=0;z<_boss.length;z++)
            {
                _boss[z]=_boss[u];
            }
        }
        else
        {
            //switch u and v
            _set[_boss[v]]=_set[_boss[v]];
            //union(_set[_boss[v]],_set[_boss[u]]);
            _size[_boss[v]]+=_size[_boss[u]];

            for(int z=0;z<_boss.length;z++)
            {
                _boss[z]=_boss[v];
            }
        }
    }

Solution

  • Step 2 mean that the set u now become the union set of u and v, so you cannot assign set[v] = set[v] (u and v is short for boss[u], boss[v] , respectively). So, if set u is {u} and set v is {v}, after this step, set u will be {u,v}, one more example is set u = {1,2} , set v = {3,4}, so after this, set u = {1,2,3,4}. Depending on what data structure you are using, you will need to implement it differently. One way is using ArrayList

    ArrayList<Integer> set[] = new ArrayList[max];
    //Initialize each set, add element into set
    for(int i = 0; i < max; i++)
       set[i] = new ArrayList();
       set[i].add(i);
    //For step 2
    set[boss[u]].addAll(set[boss[v]]);
    

    And the last thing is, your step 4 is wrong, for your current implementation, you just add every element into set[boss[u]], but in this step, they only require those that are in set[boss[v]]. So:

            int bossV = boss[v];//This is important! Answer why this is needed by yourself.
            for(int z=0;z<_boss.length;z++)
            {
                if(boss[z] == bossV)
                   _boss[z]=_boss[u];
            }
    

    Small notice: this version you are using is not the fastest version for union-find, try to read more about it!