Data Structures, Algorithms, & Applications in Java
Chapter 12, Exercise 61

One way to generate a sequence of union and find operations is to generate a sequence of n combine operations (see page 245 of text). We use this strategy with m = 1.5 * n (this choice is rather arbitrary). For n we use the values 1000, 2000, 4000, ..., 128000 (again, an arbitrary choice). For each we average over a minimum of 10 sequences of combine operations. For some n more than 10 sequences are used, because, for timing accuracy reasons, we require that at least 1 second be spent on each, code class=code>n. The code for UnionFindWithTrees is given below. To get the code for FastUnionFind simply comment out the line
UnionFindWithTrees s = new UnionFindWithTrees(n[i]));
and uncomment the preceding line.
public class TimeUnionFind
{
   public static void main(String [] args)
   {
      int [] n = {1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000};
                  // number elements
      int numberOfNs = 8;
      int minSequences = 10;  // average over at least this many sequences
      int sequenceFactor = 5; // sequence length = sequenceFactor * n
      for (int i = 0; i < numberOfNs; i++)
      {// find average time for n[i] elements
         int counter = 0;  // number of sequences done so far
         long startTime = System.currentTimeMillis();
         int numberOfCombines = 5 * n[i];
         Random r = new Random();

         // use at least minSequences sequences of 5*n[i] combine operations
         // also make sure at least 1 second has elapsed
         while (counter < minSequences ||
                System.currentTimeMillis() - startTime < 1000)
         {
            // initialize for n[i] elements
            // FastUnionFind s = new FastUnionFind(n[i]);
            UnionFindWithTrees s = new UnionFindWithTrees(n[i]);

            // do the combine operations
            for (int q = 0; q <= numberOfCombines; q++)
            {
               // select two elements at random
               int u = r.nextInt(n[i]) + 1;             
               int v = r.nextInt(n[i]) + 1;             

               // do two find operations
               int uSet = s.find(u);
               int vSet = s.find(v);

               // do a union only if uSet != vSet
               if (uSet != vSet)
                  s.union(uSet, vSet);
            }
            counter++;
         }

         long timePerSequence = (System.currentTimeMillis() - startTime)
                                / counter;
         
         System.out.println("n = " + n[i] + "   number of sequences = "
                            + counter + "   time/sequence = " +
                            timePerSequence + " ms"); 
      }
   }
}



The measured times per sequence (in milliseconds) are given below. ``-'' indicates the time was not measured because it is too much.
n UnionFindWithTrees FastUnionFind
1000 14 5
2000 43 25
4000 176 73
8000 1966 137
16000 10485 165
32000 50378 258
64000 - 626
128000 - 1340


The times are plotted below. Bullets are used for UnionFindWithTrees and deltas are used for FastUnionFind.