/******************************************************************************* * Copyright (c) 2012-present Jakub Kováč, Jozef Brandýs, Katarína Kotrlová, * Pavol Lukča, Ladislav Pápay, Viktor Tomkovič, Tatiana Tóthová * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package algvis.ds.unionfind; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Hashtable; import algvis.core.DataStructure; import algvis.core.MyRandom; import algvis.core.history.HashtableStoreSupport; import algvis.core.visual.ZDepth; import algvis.ds.unionfind.UnionFindFind.FindHeuristic; import algvis.ds.unionfind.UnionFindUnion.UnionHeuristic; import algvis.ui.VisPanel; import algvis.ui.view.Alignment; import algvis.ui.view.ClickListener; import algvis.ui.view.View; public class UnionFind extends DataStructure implements ClickListener { public static String adtName = "ufa"; public static String dsName = "ufi"; public int count = 0; private ArrayList<UnionFindNode> sets = new ArrayList<UnionFindNode>(); private ArrayList<UnionFindNode> vertices = new ArrayList<UnionFindNode>(); public FindHeuristic pathCompression = FindHeuristic.NONE; public UnionHeuristic unionState = UnionHeuristic.NONE; public UnionFindNode firstSelected = null; public UnionFindNode secondSelected = null; @Override public String getName() { return "ufi"; } public UnionFind(VisPanel M) { super(M); M.screen.V.align = Alignment.LEFT; M.screen.V.setDS(this); count = 0; } /** adds to sets and vertices */ void add(UnionFindNode n) { count++; sets.add(n); vertices.add(n); } public void removeFromSets(UnionFindNode n) { sets.remove(n); } @Override public String stats() { return ""; } @Override public void insert(int x) { } public void makeSet(int N) { for (int i = 0; i < N; i++) { add(new UnionFindNode(this, count, ZDepth.NODE)); } reposition(); } public void find(UnionFindNode u) { start(new UnionFindFind(this, u)); } public void union(UnionFindNode u, UnionFindNode v) { start(new UnionFindUnion(this, u, v)); } @Override public void random(int n) { for (int i = 0; i < n; ++i) { union(at(MyRandom.Int(count)), at(MyRandom.Int(count))); } } @Override public void clear() { count = 0; sets = new ArrayList<UnionFindNode>(); vertices = new ArrayList<UnionFindNode>(); makeSet(10); setStats(); } @Override public void draw(View V) { if (sets != null) { for (final UnionFindNode set : sets) { set.drawTree(V); } } } @Override public void move() { if (sets != null) { for (final UnionFindNode set : sets) { set.moveTree(); } } } @Override public Rectangle2D getBoundingBox() { Rectangle2D retVal = null; if (sets != null) { for (final UnionFindNode set : sets) { final Rectangle2D sBB = set.getBoundingBox(); if (retVal == null) { retVal = sBB; } else if (sBB != null) { retVal = retVal.createUnion(sBB); } } } return retVal; } @Override protected void endAnimation() { if (sets != null) { for (final UnionFindNode set : sets) { set.endAnimation(); } } } @Override protected boolean isAnimationDone() { if (sets != null) { for (final UnionFindNode set : sets) { if (!set.isAnimationDone()) { return false; } } } return true; } public void reposition() { if (sets != null) { int ey2 = -9999999; int ey1 = 9999999; for (final UnionFindNode set : sets) { y1 = y2 = 0; set.reposition(); if (y1 < ey1) { ey1 = y1; } if (y2 > ey2) { ey2 = y2; } } y1 = ey1; y2 = ey2; x1 = x2 = 0; int shift = -sets.get(0).leftw; x1 = shift; for (final UnionFindNode set : sets) { shift += set.leftw; set.shift(shift, 0); shift += set.rightw; } x2 = shift; panel.screen.V.setBounds(x1, y1, x2, y2); } } public UnionFindNode at(int elementAt) { return vertices.get(elementAt); } boolean isSelected(UnionFindNode u) { return (u == firstSelected) || (u == secondSelected); } @Override public void mouseClicked(int x, int y) { UnionFindNode u = null; int i = 0; final int j = sets.size(); do { u = (UnionFindNode) sets.get(i).find(x, y); i++; } while ((u == null) && (i < j)); if (u != null) { if (isSelected(u)) { u.unmark(); if (u == secondSelected) { secondSelected = null; } else if (u == firstSelected) { firstSelected = secondSelected; secondSelected = null; } } else { u.mark(); if (firstSelected == null) { firstSelected = u; } else if (secondSelected == null) { secondSelected = u; } else { firstSelected.unmark(); firstSelected = secondSelected; secondSelected = u; } } } } @Override public void storeState(Hashtable<Object, Object> state) { super.storeState(state); HashtableStoreSupport.store(state, hash + "count", count); HashtableStoreSupport.store(state, hash + "sets", sets.clone()); for (final UnionFindNode node : sets) { node.storeState(state); } HashtableStoreSupport.store(state, hash + "vertices", vertices.clone()); for (final UnionFindNode node : vertices) { node.storeState(state); } } @Override public void restoreState(Hashtable<?, ?> state) { super.restoreState(state); final Object count = state.get(hash + "count"); if (count != null) { this.count = (Integer) HashtableStoreSupport.restore(count); } final Object sets = state.get(hash + "sets"); if (sets != null) { this.sets = (ArrayList<UnionFindNode>) HashtableStoreSupport .restore(sets); } for (final UnionFindNode node : this.sets) { node.restoreState(state); } final Object vertices = state.get(hash + "vertices"); if (vertices != null) { this.vertices = (ArrayList<UnionFindNode>) HashtableStoreSupport .restore(vertices); } for (final UnionFindNode node : this.vertices) { node.restoreState(state); } } }