00001 package edu.ksu.cis.bandera.abstraction.util;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.util.*;
00036
00037 public class UnionFindSet implements Set {
00038 private Hashtable elements = new Hashtable();
00039 private Hashtable partAttrTable = new Hashtable();
00040 private class Element {
00041 int rank;
00042 Element parent;
00043 Object object;
00044 Element(int rank, Object object) {
00045 this.rank = rank;
00046 this.parent = this;
00047 this.object = object;
00048 }
00049 }
00050
00051
00052
00053 public UnionFindSet() {}
00054
00055
00056
00057 public UnionFindSet(Collection c) {
00058 for (Iterator i = new HashSet(c).iterator(); i.hasNext();) {
00059 Object o = i.next();
00060 elements.put(o, new Element(0, o));
00061 }
00062 }
00063
00064
00065
00066
00067
00068 public boolean add(Object o) {
00069 if (find(o) == null) {
00070 elements.put(o, new Element(0, o));
00071 return true;
00072 } else {
00073 return false;
00074 }
00075 }
00076
00077
00078
00079
00080
00081 public boolean addAll(Collection c) {
00082 boolean result = false;
00083 for (Iterator i = c.iterator(); i.hasNext();) {
00084 result = result || add(i.next());
00085 }
00086 return result;
00087 }
00088
00089
00090
00091
00092
00093
00094 public boolean addAllTo(Collection c, Object orep) {
00095 boolean result = false;
00096 for (Iterator i = c.iterator(); i.hasNext();) {
00097 result = result || addTo(i.next(), orep);
00098 }
00099 return result;
00100 }
00101
00102
00103
00104
00105
00106
00107 public boolean addTo(Object o, Object orep) {
00108 if (add(o)) {
00109 union(o, orep);
00110 }
00111 return false;
00112 }
00113
00114
00115
00116 public void clear() {
00117 elements = new Hashtable();
00118 partAttrTable = new Hashtable();
00119 }
00120
00121
00122
00123
00124
00125 public boolean contains(Object o) {
00126 return toSet().contains(o);
00127 }
00128
00129
00130
00131
00132
00133 public boolean containsAll(Collection c) {
00134 return toSet().containsAll(c);
00135 }
00136
00137
00138
00139
00140
00141 public Object find(Object o) {
00142 try {
00143 Element e = (Element) elements.get(o);
00144 if (e == null) return null;
00145 Element above = e.parent;
00146 while (above != above.parent) {
00147 e.parent = above.parent;
00148 above = above.parent.parent;
00149 }
00150 return above.object;
00151 } catch (Exception e) {
00152 return null;
00153 }
00154 }
00155
00156
00157
00158
00159
00160 public Object getAttribute(Object o) {
00161 o = find(o);
00162 if (o == null) return null;
00163 else return partAttrTable.get(o);
00164 }
00165
00166
00167
00168
00169 public boolean isEmpty() {
00170 return elements.size() == 0;
00171 }
00172
00173
00174
00175
00176 public Iterator iterator() {
00177 return toSet().iterator();
00178 }
00179
00180
00181
00182
00183 public static void main(String[] args) {
00184 if (args.length != 2) {
00185 System.out.println("needs two positive-integer arguments");
00186 return;
00187 }
00188
00189 UnionFindSet ufs = new UnionFindSet();
00190
00191 int size = Integer.parseInt(args[0]);
00192 int cmod = Integer.parseInt(args[1]);
00193
00194 Integer[] ints = new Integer[size];
00195
00196 for (int i = 0; i < size; i++) {
00197 ufs.add(ints[i] = new Integer(i));
00198 }
00199
00200 System.out.println(ufs.toString());
00201
00202 for (int i = 0; i < size; i++) {
00203 for (int j = 0; j < cmod; j++) {
00204 if (i % cmod == j) {
00205 ufs.union(ints[j], ints[i]);
00206 }
00207 }
00208 }
00209
00210 System.out.println(ufs);
00211
00212 for (int i = 0; i < size; i++) {
00213 System.out.println(ints[i] + " is represented as " + ufs.find(ints[i]));
00214 }
00215 }
00216
00217
00218
00219
00220
00221 public boolean remove(Object object) {
00222 try {
00223 Element e = (Element) elements.get(object);
00224 if (e.parent == e) {
00225 Element top = null;
00226 for (Enumeration enum = elements.elements(); enum.hasMoreElements();) {
00227 Element e2 = (Element) enum.nextElement();
00228 if (e2.parent == e) {
00229 if (top == null) {
00230 top = e2;
00231 top.rank = e.rank;
00232 }
00233 e2.parent = top;
00234 }
00235 }
00236 partAttrTable.put(top.object, partAttrTable.get(e.object));
00237 } else {
00238 for (Enumeration enum = elements.elements(); enum.hasMoreElements();) {
00239 Element e2 = (Element) enum.nextElement();
00240 if (e2.parent == e) {
00241 e2.parent = e.parent;
00242 }
00243 }
00244 }
00245 elements.remove(object);
00246 return true;
00247 } catch (Exception e) {
00248 return false;
00249 }
00250 }
00251
00252
00253
00254
00255
00256 public boolean removeAll(Collection c) {
00257 boolean result = false;
00258 for (Iterator i = c.iterator(); i.hasNext();) {
00259 result = result || remove(i.next());
00260 }
00261 return result;
00262 }
00263
00264
00265
00266
00267
00268 public boolean retainAll(Collection c) {
00269 boolean result = false;
00270 for (Enumeration e = elements.elements(); e.hasMoreElements();) {
00271 Object o = e.nextElement();
00272 if (!c.contains(o)) {
00273 remove(o);
00274 }
00275 }
00276 return result;
00277 }
00278
00279
00280
00281
00282
00283
00284 public boolean setAttribute(Object o, Object attr) {
00285 o = find(o);
00286 if (o == null) return false;
00287 partAttrTable.put(o, attr);
00288 return true;
00289 }
00290
00291
00292
00293
00294 public int size() {
00295 return toSet().size();
00296 }
00297
00298
00299
00300
00301 public Object[] toArray() {
00302 return toSet().toArray();
00303 }
00304
00305
00306
00307
00308
00309 public Object[] toArray(Object[] objects) {
00310 return null;
00311 }
00312
00313
00314
00315
00316 private Set toSet() {
00317 Hashtable table = new Hashtable();
00318 for (Enumeration e = elements.elements(); e.hasMoreElements();) {
00319 Element el = (Element) e.nextElement();
00320 Element rel = (Element) elements.get(find(el.object));
00321 if (table.get(rel) == null) {
00322 table.put(rel, new HashSet());
00323 }
00324 ((HashSet) table.get(rel)).add(el.object);
00325 }
00326 HashSet set = new HashSet();
00327 for (Enumeration e = table.elements(); e.hasMoreElements();) {
00328 set.add(e.nextElement());
00329 }
00330 return set;
00331 }
00332
00333
00334
00335
00336 public String toString() {
00337 Set set = toSet();
00338 StringBuffer temp = new StringBuffer(set.size() + "= {\n");
00339 for (Iterator i = set.iterator(); i.hasNext();) {
00340 Set s = (Set) i.next();
00341
00342 temp.append("(" + getAttribute(s.iterator().next()) + ", " + s + "),\n");
00343 }
00344 temp.append("}\n");
00345 return temp.toString();
00346 }
00347
00348
00349
00350
00351
00352
00353 public boolean union(Object o1, Object o2) {
00354 o1 = find(o1);
00355 o2 = find(o2);
00356 if ((o1 == null) || (o2 == null))
00357 return false;
00358 if (getAttribute(o1) != null && getAttribute(o2) != null)
00359 if (getAttribute(o1) != getAttribute(o2))
00360 System.out.println("Warning: trying to merge two partitions that have different attributes");
00361 Object attr = getAttribute(o1);
00362 if (attr == null)
00363 attr = getAttribute(o2);
00364 partAttrTable.remove(o1);
00365 partAttrTable.remove(o2);
00366 try {
00367 Element e1 = (Element) elements.get(o1);
00368 Element e2 = (Element) elements.get(o2);
00369 if (e1.rank >= e2.rank) {
00370 e2.parent = e1;
00371 if (e1.rank == e2.rank) {
00372 e1.rank++;
00373 }
00374 } else {
00375 e1.parent = e2;
00376 }
00377 } catch (Exception e) {
00378 return false;
00379 }
00380 o1 = find(o1);
00381 if (attr != null)
00382 partAttrTable.put(o1, attr);
00383 return true;
00384 }
00385 }