123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
-
- 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();
- }
- }
-
- }
|