Class Name: 
kiasan.examples.disjsets.DisjSetsFast

Report Rendered: Mon May 04 11:28:33 CDT 2009, by Sireum/Kiasan for Java v0.1.20090504

Methods Covered:
PercentRatio
Class / Method T E Instruction Coverage Branch Coverage Time
55 0
  23/23
  100%
  2/2
  100%
0.022s
60 0
  38/38
  100%
  4/4
  100%
0.014s
Total
115 0
  61/61
  100%
  6/6
  100%
0.036s
Source Code:
1   package kiasan.examples.disjsets;
2   
3   // DisjSetsFast class
4   //
5   // CONSTRUCTION: with int representing initial number of sets
6   //
7   // ******************PUBLIC OPERATIONS*********************
8   // void union( root1, root2 ) --> Merge two sets
9   // int find( x )              --> Return set containing x
10  // ******************ERRORS********************************
11  // No error checking is performed
12  
13  /**
14   * Disjoint set class, using union by rank and path compression. Elements in the
15   * set are numbered starting at 0.
16   * 
17   * @author Mark Allen Weiss
18   */
19  public class DisjSetsFast {
20    // Test main; all finds on same output line should be identical
21    public static void main(final String[] args) {
22      final int NumElements = 128;
23      final int NumInSameSet = 16;
24  
25      final DisjSetsFast ds = new DisjSetsFast(NumElements);
26      int set1, set2;
27  
28      for (int k = 1; k < NumInSameSet; k *= 2) {
29        for (int j = 0; j + k < NumElements; j += 2 * k) {
30          set1 = ds.find(j);
31          set2 = ds.find(+ k);
32          ds.union(set1, set2);
33        }
34      }
35  
36      for (int i = 0; i < NumElements; i++) {
37        System.out.print(ds.find(i) + "*");
38        if (% NumInSameSet == NumInSameSet - 1) {
39          System.out.println();
40        }
41      }
42      System.out.println();
43    }
44  
45    private final int[] s;
46  
47    /**
48     * Construct the disjoint sets object.
49     * 
50     * @param numElements
51     *          the initial number of disjoint sets.
52     */
53    public DisjSetsFast(final int numElements) {
54      this.= new int[numElements];
55      for (int i = 0; i < this.s.length; i++) {
56        this.s[i] = -1;
57      }
58    }
59  
60    boolean acyclic() {
61      final boolean[] visited = new boolean[this.s.length];
62      for (int i = 0; i < visited.length; i++) {
63        visited[i] = false;
64      }
65      final int[] parents = new int[this.s.length];
66  
67      for (int i = 0; i < this.s.length; i++) {
68        if (!visited[i]) {
69          int numParents = 0;
70          int currentIndex = i;
71          while (this.s[currentIndex] >= 0) {
72            for (int j = 0; j < numParents - 1; j++) {
73              if (parents[j] == this.s[currentIndex]) {
74                return false;
75              }
76            }
77            parents[numParents] = this.s[currentIndex];
78            numParents++;
79            visited[currentIndex] = true;
80            currentIndex = this.s[currentIndex];
81          }
82        }
83      }
84      return true;
85    }
86  
87    public int find(final int x) {
88      if (this.s[x] < 0) {
89        return x;
90      } else {
91        return this.s[x] = find(this.s[x]);
92      }
93    }
94  
95    /**
96     * Perform a find with path compression. Error checks omitted again for
97     * simplicity.
98     * 
99     * @param x
100    *          the element being searched for.
101    * @return the set containing x.
102    */
103   //@ requires (this.s != null) && this.goodValues() && this.acyclic() && (x >= 0) && (x < this.s.length);
104   //@ ensures this.s[\result] < 0;
105   public int Find(final int x) {
106     return find(x);
107   }
108 
109   boolean goodValues() {
110     boolean hasRoot = false;
111     for (int i = 0; i < this.s.length; i++) {
112       if ((this.s[i] < 0) && (this.s[i] >= 0 - this.s.length)) {
113         hasRoot = true;
114       } else if (!(((this.s[i] >= 0) && (this.s[i] < this.s.length)))) {
115         return false;
116       }
117     }
118     return hasRoot;
119   }
120 
121   /**
122    * Union two disjoint sets using the height heuristic. For simplicity, we
123    * assume root1 and root2 are distinct and represent set names.
124    * 
125    * @param root1
126    *          the root of set 1.
127    * @param root2
128    *          the root of set 2.
129    */
130   //@ requires (this.s != null) && this.goodValues() && this.acyclic() && (root1 >= 0) && (root1 < this.s.length) && (root2 >= 0) && (root2 < this.s.length) && (root1 != root2) && (this.s[root1] < 0) && (this.s[root2] < 0);
131   //@ ensures this.find(root1) == this.find(root2);
132   public void union(final int root1, final int root2) {
133     if (this.s[root2] < this.s[root1]) {
134       this.s[root1] = root2; // Make root2 new root
135     } else {
136       if (this.s[root1] == this.s[root2]) {
137         this.s[root1]--; // Update height if same
138       }
139       this.s[root2] = root1; // Make root1 new root
140     }
141   }
142 }