--- /dev/null
+
+package common;
+
+import java.lang.reflect.Array;
+import java.util.*;
+
+/**
+ * Class SkipList implements a skip list that uses int primitives for
+ * the element keys. The modification methods defined by <code>Set</code>
+ * are not supported. Instead, methods with keys are required. Note that
+ * the keys have a many to one relationship with the elements (that is,
+ * a range of key values will map to a single element).
+ *
+ * <p><b>Note that this implementation is not synchronized.</b> If multiple
+ * threads access a set concurrently, and at least one of the threads modifies
+ * the set, it <i>must</i> be synchronized externally. This is typically
+ * accomplished by synchronizing on some object that naturally encapsulates
+ * the set. If no such object exists, the set should be "wrapped" using the
+ * <code>Collections.synchronizedList</code> method. This is best done at
+ * creation time, to prevent accidental unsynchronized access to the set:</p>
+ *<pre>
+ * List l = Collections.synchronizedList(new DisjointSet(...));
+ *</pre>
+ *
+ * <p>The Iterators returned by this class's <tt>iterator</tt> method are
+ * <i>fail-fast</i>: if the set is modified at any time after the iterator is
+ * created, in any way except through the iterator's own <tt>remove</tt>
+ * method, the iterator will throw a <tt>ConcurrentModificationException</tt>.
+ * Thus, in the face of concurrent modification, the iterator fails quickly
+ * and cleanly, rather than risking arbitrary, non-deterministic behavior at
+ * an undetermined time in the future.</p>
+ *
+ * @author Original version: Nathan Fiedler (2001)
+ * @author Several important bugfixes: Holger Hoffstaette
+ *
+ * @version $Revision$ $Date$
+ */
+
+public class SkipList<T extends Comparable> extends Object implements Set<T>, Iterable<T>
+{
+ /** Optimal probability of most skip lists. */
+ public static final double OPTIMAL_P = 0.25;
+
+ // MaxLevel = L(N) (where N is an upper bound on the number of
+ // elements in a skip list). If p = 0.5, using MaxLevel = 16 is
+ // appropriate for data structures containing up to 2^16 elements.
+ /** Maximum level of any SkipList instance. */
+ protected final int MAX_LEVEL;
+
+ /** Probability value for this skip list. */
+ protected final double P;
+
+ /** Tail of this skip list. */
+ protected final SkipListElement<T> _NIL;
+
+ /** The level of this skip list. */
+ protected int _listLevel;
+
+ /** Header is an element with no data. */
+ protected SkipListElement<T> _listHeader;
+
+ /** Number of elements in this skip list. */
+ protected int _elementCount;
+
+ /** Increments each time the list changes. */
+ protected int _modCount;
+
+ /**
+ * Constructs an empty SkipList using the default probability
+ * and maximum element size.
+ */
+ public SkipList()
+ {
+ this(OPTIMAL_P, (int)Math.ceil(Math.log(Integer.MAX_VALUE) / Math.log(1 / OPTIMAL_P)) - 1);
+ }
+
+ /**
+ * Constructs an empty SkipList object using the given probability
+ * and maximum level.
+ *
+ * @param probability skip list probability value.
+ * @param maxLevel maximum skip list level.
+ */
+ public SkipList(double probability, int maxLevel)
+ {
+ P = probability;
+ MAX_LEVEL = maxLevel;
+
+ // Header is the root of our skip list.
+ _listHeader = new SkipListElement<T>(MAX_LEVEL, Integer.MIN_VALUE, null);
+
+ // Allocate NIL with a key greater than any valid key;
+ // all levels of skip lists terminate on NIL.
+ _NIL = new SkipListElement<T>(0, Integer.MAX_VALUE, null);
+
+ this.clear();
+ }
+
+ public SkipList(Collection<? extends T> c)
+ {
+ this();
+ this.addAll(c);
+ }
+
+ public boolean add(T o)
+ {
+ this.insert(o.hashCode(), o);
+ return true;
+ }
+
+ public boolean addAll(Collection<? extends T> c)
+ {
+ boolean added = false;
+
+ if (!c.isEmpty())
+ {
+ for (Iterator<? extends T> iter = c.iterator(); iter.hasNext();)
+ {
+ added |= this.add(iter.next());
+ }
+ }
+
+ return added;
+ }
+
+ public void clear()
+ {
+ // List level is started at one.
+ _listLevel = 1;
+
+ // All forward pointers of list's header point to NIL.
+ for (int i = _listHeader._forward.length - 1; i >= 0; i--)
+ {
+ _listHeader._forward[i] = _NIL;
+ }
+
+ // Reset element count.
+ _elementCount = 0;
+ _modCount++;
+ }
+
+ public boolean contains(Object o)
+ {
+ for (SkipListElement e = _listHeader._forward[0]; e != _NIL; e = e._forward[0])
+ {
+ if ((e._value == o) || e._value != null && e._value.equals(o))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ if ((this.size() < c.size()) || (this.isEmpty() && c.isEmpty()))
+ {
+ return false;
+ }
+
+ for (Iterator<?> iter = c.iterator(); iter.hasNext();)
+ {
+ if (!this.contains(iter.next()))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Removes the element with the given key from the list.
+ *
+ * @param searchKey key of element to remove.
+ * @return <code>true</code> if element was found and removed.
+ */
+ public boolean remove(int searchKey)
+ {
+ SkipListElement[] update = new SkipListElement[MAX_LEVEL];
+ SkipListElement e = _listHeader;
+
+ for (int i = _listLevel; i >= 0; i--)
+ {
+ while (e._forward[i]._key < searchKey)
+ {
+ e = e._forward[i];
+ }
+
+ update[i] = e;
+ }
+
+ e = e._forward[0];
+
+ if (e._key == searchKey)
+ {
+ for (int i = 0; i < _listLevel; i++)
+ {
+ if (update[i]._forward[i] != e)
+ {
+ break;
+ }
+
+ update[i]._forward[i] = e._forward[i];
+ }
+
+ while (_listLevel > 0 && _listHeader._forward[_listLevel] == _NIL)
+ {
+ _listLevel--;
+ }
+
+ _elementCount--;
+ _modCount++;
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Inserts the element using the given search key. If an element
+ * with the same key already exists in the skip lists, its value
+ * will be replaced with <code>newValue</code>.
+ *
+ * @param searchKey key for element.
+ * @param newValue new element to insert.
+ */
+ @SuppressWarnings("unchecked")
+ public void insert(int searchKey, T newValue)
+ {
+ SkipListElement<T>[] update = new SkipListElement[MAX_LEVEL];
+ SkipListElement<T> e = _listHeader;
+
+ for (int i = _listLevel - 1; i >= 0; i--)
+ {
+ while (e._forward[i]._key < searchKey)
+ {
+ e = e._forward[i];
+ }
+
+ update[i] = e;
+ }
+
+ e = e._forward[0];
+
+ if (e._key == searchKey)
+ {
+ e._value = newValue;
+ }
+ else
+ {
+ int lvl = randomLevel();
+ if (lvl > _listLevel)
+ {
+ for (int i = _listLevel; i <= lvl; i++)
+ {
+ update[i] = _listHeader;
+ }
+
+ _listLevel = lvl;
+ }
+
+ e = new SkipListElement<T>(lvl, searchKey, newValue);
+
+ for (int i = 0; i < lvl; i++)
+ {
+ e._forward[i] = update[i]._forward[i];
+ update[i]._forward[i] = e;
+ }
+ }
+
+ _elementCount++;
+ _modCount++;
+ }
+
+ public boolean isEmpty()
+ {
+ return (_elementCount == 0);
+ }
+
+ public Iterator<T> iterator()
+ {
+ return new SkipListIterator<T>();
+ }
+
+ /**
+ * Return a random level.
+ *
+ * @return level selected randomly.
+ */
+ protected int randomLevel()
+ {
+ int lvl = 1;
+
+ while (lvl < MAX_LEVEL && Math.random() < P)
+ {
+ lvl++;
+ }
+
+ return lvl;
+ }
+
+ public boolean remove(Object o)
+ {
+ return this.remove(o.hashCode());
+ }
+
+ public boolean removeAll(Collection c)
+ {
+ boolean removed = false;
+
+ for (Iterator iter = c.iterator(); iter.hasNext();)
+ {
+ removed |= this.remove(iter.next());
+ }
+
+ return removed;
+ }
+
+ public boolean retainAll(Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Searches for the element with the given key.
+ *
+ * @param searchKey key to look for.
+ * @return element if found, null if not found. Note that you may
+ * not want to store nulls in this list as it would then
+ * be difficult to know the difference.
+ */
+ public T get(int searchKey)
+ {
+ SkipListElement<T> e = _listHeader;
+
+ for (int i = _listLevel - 1; i >= 0; i--)
+ {
+ while (e._forward[i]._key < searchKey)
+ {
+ e = e._forward[i];
+ }
+ }
+
+ e = e._forward[0];
+
+ if (e._key == searchKey)
+ {
+ return e._value;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Searches for the element with a key that is the least smaller
+ * value of the given key.
+ *
+ * @param searchKey key to look for.
+ * @return element if found, null if not found.
+ */
+ public T searchLeastSmaller(int searchKey)
+ {
+ SkipListElement<T> e = _listHeader;
+
+ for (int i = _listLevel - 1; i >= 0; i--)
+ {
+ while (e._forward[i]._key < searchKey)
+ {
+ e = e._forward[i];
+ }
+ }
+
+ if (e._forward[0]._key == searchKey)
+ {
+ return e._forward[0]._value;
+ }
+ else
+ {
+ return e._value;
+ }
+ }
+
+ /**
+ * Searches for the element just after the one found using the
+ * given key (where the key value may be the least smaller of
+ * the given key).
+ *
+ * @param searchKey key to look for.
+ * @return next element if found, null if not found.
+ */
+ public T searchNextLarger(int searchKey)
+ {
+ SkipListElement<T> e = _listHeader;
+
+ for (int i = _listLevel - 1; i >= 0; i--)
+ {
+ while (e._forward[i]._key < searchKey)
+ {
+ e = e._forward[i];
+ }
+ }
+
+ SkipListElement<T> t = null;
+
+ if (e._forward[0]._key == searchKey)
+ {
+ t = e._forward[0];
+ }
+ else
+ {
+ t = e;
+ }
+
+ if (t._forward[0] == _NIL)
+ {
+ return null;
+ }
+ else
+ {
+ return t._forward[0]._value;
+ }
+ }
+
+ /**
+ * Returns the number of elements in this list. If this list contains
+ * more than <tt>Integer.MAX_VALUE</tt> elements, returns
+ * <tt>Integer.MAX_VALUE</tt>.
+ *
+ * @return the number of elements in this list.
+ */
+ public int size()
+ {
+ return _elementCount;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this list in
+ * proper sequence. Obeys the general contract of the
+ * <tt>Collection.toArray()</tt> method.
+ *
+ * @return an array containing all of the elements in this list in
+ * proper sequence.
+ * @see Arrays#asList(Object[])
+ */
+ public Object[] toArray()
+ {
+ return toArray(new Object[_elementCount]);
+ }
+
+ /**
+ * Returns an array containing all of the elements in this list in
+ * proper sequence; the runtime type of the returned array is that
+ * of the specified array. Obeys the general contract of the
+ * <tt>Collection.toArray(Object[])</tt> method.
+ *
+ * @param a the array into which the elements of this list are to
+ * be stored, if it is big enough; otherwise, a new array
+ * of the same runtime type is allocated for this purpose.
+ * @return an array containing the elements of this list.
+ * @exception ArrayStoreException
+ * Throw if the runtime type of the specified array is not
+ * a supertype of the runtime type of every element in this
+ * list.
+ */
+ @SuppressWarnings({"unchecked","hiding"})
+ public <T> T[] toArray(T[] a)
+ {
+ int size = this.size();
+
+ if (a.length < size)
+ {
+ a = (T[])Array.newInstance(a.getClass().getComponentType(), size);
+ }
+
+ SkipListElement e = _listHeader;
+
+ for (int i = 0; i < _elementCount; i++)
+ {
+ a[i] = (T)e._forward[0]._value;
+ e = e._forward[0];
+ }
+
+ return a;
+ }
+
+ /**
+ * Class Element represents an element of a skip list.
+ */
+ protected class SkipListElement<E> extends Object
+ {
+ /** Key of element. */
+ int _key;
+
+ /** Value of element. */
+ E _value;
+
+ /** List of forward pointers. */
+ SkipListElement<E>[] _forward;
+
+ /**
+ * Constructs an Element for the given key and value.
+ *
+ * @param level level for this node (number of forward pointers).
+ * @param key key for element.
+ * @param value value for element.
+ */
+ @SuppressWarnings("unchecked")
+ public SkipListElement(int level, int key, E value)
+ {
+ _key = key;
+ _value = value;
+ _forward = new SkipListElement[level];
+ }
+ }
+
+ /**
+ * An iterator over a skip list.
+ */
+ protected class SkipListIterator<E> implements Iterator<T>
+ {
+ /** Index into the skip list. */
+ protected int _index;
+
+ /** The modCount of the list at the time we were instantiated. */
+ protected int _listModCount;
+
+ /** Current element being examined. */
+ protected SkipListElement<T> _elem;
+
+ /**
+ * Constructs a skip list iterator.
+ */
+ public SkipListIterator()
+ {
+ _listModCount = SkipList.this._modCount;
+ _elem = _listHeader;
+ }
+
+ /**
+ * Returns <tt>true</tt> if the iteration has more elements. (In
+ * other words, returns <tt>true</tt> if <tt>next</tt> would return
+ * an element rather than throwing an exception.)
+ *
+ * @return <tt>true</tt> if the iterator has more elements.
+ */
+ public boolean hasNext()
+ {
+ if (this._listModCount != SkipList.this._modCount)
+ {
+ throw new ConcurrentModificationException();
+ }
+
+ return _elem._forward[0] != _NIL;
+ }
+
+ /**
+ * Returns the next element in the iteration.
+ *
+ * @return the next element in the iteration.
+ * @exception NoSuchElementException
+ * iteration has no more elements.
+ */
+ public T next()
+ {
+ if (this._listModCount != SkipList.this._modCount)
+ {
+ throw new ConcurrentModificationException();
+ }
+
+ if (this.hasNext())
+ {
+ _elem = _elem._forward[0];
+ return _elem._value;
+ }
+ else
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}