6

I didn't find any good implementation of Disjoint Set in C# using Union by rank implementation so I implemented my own. It works in O(log n) time complexity.

Is there faster (or built-in implementation in C#) or I can work with my own implementation?

class DisjointSetUBR
{
    int[] parent;
    int[] rank; // height of tree

    public DisjointSetUBR(int[] arr)
    {
        parent = new int[arr.Length +1];
        rank = new int[arr.Length + 1];
    }

    public void MakeSet(int i)
    {
        parent[i] = i;
    }

    public int Find(int i)
    {
        while (i!=parent[i]) // If i is not root of tree we set i to his parent until we reach root (parent of all parents)
        {
            i = parent[i]; 
        }
        return i;
    }

    // Path compression, O(log*n). For practical values of n, log* n <= 5
    public int FindPath(int i)
    {
        if (i!=parent[i])
        {
            parent[i] = FindPath(parent[i]);
        }
        return parent[i];
    }

    public void Union(int i, int j)
    {
        int i_id = Find(i); // Find the root of first tree (set) and store it in i_id
        int j_id = Find(j); // // Find the root of second tree (set) and store it in j_id

        if (i_id == j_id) // If roots are equal (they have same parents) than they are in same tree (set)
        {
            return;
        }

        if (rank[i_id] > rank[j_id]) // If height of first tree is larger than second tree
        {
            parent[j_id] = i_id; // We hang second tree under first, parent of second tree is same as first tree
        }
        else
        {
            parent[i_id] = j_id; // We hang first tree under second, parent of first tree is same as second tree
            if (rank[i_id] == rank[j_id]) // If heights are same
            {
                rank[j_id]++; // We hang first tree under second, that means height of tree is incremented by one
            }
        }
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
gagro
  • 371
  • 7
  • 18
  • 1
    O(log* n) is the theoretical best AFAIK. So in terms of time complexity, it is impossible to do better. – Willem Van Onsem Sep 23 '17 at 18:53
  • Looks approximately fine to me (I didn't check it that accurately but it has the expected features of union by rank and path compression) but code reviews should happen on [code reviews](https://codereview.stackexchange.com/). Why does the constructor take an array that it doesn't use though? – harold Sep 23 '17 at 18:55
  • 1
    Actually there is a small thing here: the union could use the path-compression variant of find. – harold Sep 23 '17 at 19:00
  • @harold I'm using array in constructor only to initialize arrays "parent" and "rank" since those two arrays have same length as initial array. – gagro Sep 23 '17 at 19:06
  • 1
    So you could just pass in the length right? Why the array? – harold Sep 23 '17 at 19:07
  • @harold right :). Thank you. I totally missed that. – gagro Sep 23 '17 at 19:09
  • Is it really arr.Length +1 ? You don't seen to use that +1. – Kostya Sep 23 '17 at 20:17
  • To clarify your question - are you asking specifically about Union by rank implementation or is that just an example? The question seems to contradict itself somewhat. – StayOnTarget Jun 07 '18 at 13:27

1 Answers1

1
  1. In Prof. Sedgewick's "Algorithms" Book, he mentions "weighted quick-union with path compression" which is supposed to have the inverse Ackermann function amortized time for find/union.

  2. You are right, there's no any implementation of Disjoint Set in .Net.

Kostya
  • 849
  • 5
  • 14