/**
*
*/
package vroom.common.utilities;
import java.util.AbstractSequentialList;
import java.util.Arrays;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* <code>DoublyLinkedList</code>
* <p>
* Creation date: Oct 4, 2011 - 3:54:37 PM.
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a
* href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0
*/
public class DoublyLinkedIntSet extends AbstractSequentialList<Integer> implements java.io.Serializable, Set<Integer> {
/** The Constant UNDEFINED is used when an element has no or predecessor/successor. */
public final static Integer UNDEFINED = -2;
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The element id. */
private Integer mFirst;
/** The last element id. */
private Integer mLast;
/** The Length. */
private Integer mSize = 0;
/** The Predecessor of each node. */
private final Integer[] mPred;
/** The Successor of each node. */
private final Integer[] mSucc;
/**
* Creates a new <code>DoublyLinkedIntegerList</code>.
*
* @param maxValue
* the maximum value that will be stored in this list
*/
public DoublyLinkedIntSet(Integer maxValue) {
if (maxValue < 0)
throw new IllegalArgumentException("Max value cannot be negative");
mFirst = UNDEFINED;
mLast = UNDEFINED;
mSize = 0;
mPred = new Integer[maxValue + 1];
mSucc = new Integer[maxValue + 1];
Arrays.fill(mPred, UNDEFINED);
Arrays.fill(mSucc, UNDEFINED);
}
/* (non-Javadoc)
* @see java.util.AbstractList#listIterator()
*/
@Override
public DoublyLinkedIterator listIterator() {
return new DoublyLinkedIterator();
}
/* (non-Javadoc)
* @see java.util.AbstractSequentialList#listIterator(int)
*/
@Override
public DoublyLinkedIterator listIterator(int index) {
if (index > size() || index < 0)
throw new IllegalArgumentException("The specified index (" + index + ") is out of range");
DoublyLinkedIterator it = listIterator();
for (int i = 0; i < index; i++)
it.next();
return it;
}
/* (non-Javadoc)
* @see java.util.AbstractCollection#size()
*/
@Override
public int size() {
return mSize;
}
/**
* Gets the first element.
*
* @return the first element
*/
Integer getFirst() {
return mFirst;
}
/**
* Gets the last element.
*
* @return the last element
*/
Integer getLast() {
return mLast;
}
/**
* Gets the element predecessor.
*
* @param element
* the element
* @return the element predecessor
*/
Integer getPred(Integer element) {
return mPred[element];
}
/**
* Gets the element successor.
*
* @param element
* the element
* @return the element successor
*/
Integer getSucc(Integer element) {
return mSucc[element];
}
/**
* Sets the element predecessor.
*
* @param element
* the element
* @param pred
* the element predecessor
* @return the integer
*/
private Integer setPred(Integer element, Integer pred) {
return mPred[element] = pred;
}
/**
* Sets the element successor.
*
* @param element
* the element
* @param succ
* the element successor
* @return the integer
*/
private Integer setSucc(Integer element, Integer succ) {
return mSucc[element] = succ;
}
/**
* Sets the first element.
*
* @param first
* the new first element
*/
private void setFirst(Integer first) {
mFirst = first;
}
/**
* Sets the last element.
*
* @param last
* the new last element
*/
private void setLast(Integer last) {
mLast = last;
}
/**
* Insert an element.
*
* @param element
* the element to be inserted
* @param succ
* the successor of the inserted element
*/
void insert(Integer element, Integer succ) {
if (contains(element))
throw new IllegalArgumentException("Element " + element + " is already present in this permutation "
+ Utilities.toShortString(this));
int pred = getPred(succ);
if (pred != UNDEFINED)
setSucc(pred, element);
else
setFirst(element);
setPred(element, pred);
setPred(succ, element);
setSucc(element, succ);
// Update length
this.mSize++;
}
/* (non-Javadoc)
* @see java.util.AbstractList#add(java.lang.Object)
*/
@Override
public boolean add(Integer element) {
if (mLast != UNDEFINED) {// Tour is not empty
setSucc(getLast(), element);
setPred(element, getLast());
} else { // Tour is empty
// Initialize the tour
setFirst(element);
}
setLast(element);
this.mSize++;
return true;
}
/* (non-Javadoc)
* @see java.util.AbstractCollection#remove(java.lang.Object)
*/
@Override
public boolean remove(Object o) {
if (!contains(o))
return false;
Integer element = (Integer) o;
Integer pred = getPred(element);
Integer succ = getSucc(element);
if (pred != UNDEFINED)
setSucc(pred, succ);
else
setFirst(succ);
if (succ != UNDEFINED)
setPred(succ, pred);
else
setLast(pred);
// Update length
this.mSize--;
return true;
}
@Override
public void clear() {
mFirst = UNDEFINED;
mLast = UNDEFINED;
mSize = 0;
Arrays.fill(mPred, UNDEFINED);
Arrays.fill(mSucc, UNDEFINED);
}
/**
* Replace an element of this list
*
* @param oldElement
* @param newElement
* @return <code>true</code> if oldElement was replaced by newElement
*/
boolean setElement(Integer oldElement, Integer newElement) {
if (!contains(oldElement))
return false;
Integer pred = getPred(oldElement);
Integer succ = getSucc(oldElement);
if (pred != UNDEFINED)
setSucc(pred, newElement);
else
setFirst(newElement);
if (succ != UNDEFINED)
setPred(succ, newElement);
else
setLast(newElement);
setPred(newElement, pred);
setSucc(newElement, succ);
setPred(oldElement, UNDEFINED);
setSucc(oldElement, UNDEFINED);
return true;
}
/* (non-Javadoc)
* @see java.util.AbstractCollection#contains(java.lang.Object)
*/
@Override
public boolean contains(Object o) {
if (o instanceof Integer) {
Integer element = (Integer) o;
return getPred(element) != UNDEFINED || getSucc(element) != UNDEFINED || getFirst() == element;
} else
return false;
}
@Override
public Integer[] toArray() {
Integer[] array = new Integer[size()];
int i = 0;
for (Integer e : this)
array[i++] = e;
return array;
}
/**
* The Class <code>DoublyLinkedListIterator</code> is an implementation of {@link ListIterator} used to iterate over
* a {@link DoublyLinkedIntSet}
* <p>
* Creation date: Oct 4, 2011 - 4:25:51 PM.
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a
* href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0
*/
public class DoublyLinkedIterator implements ListIterator<Integer> {
/** <code>true</code> if the value of <code>cursor</code> cannot be trusted. */
private final boolean noCursor;
/** The current node, which will be returned at the next call to {@link #next()}. */
private int current;
/** The cursor. */
private int cursor;
/**
* Instantiates a new tRSP tour iterator.
*/
protected DoublyLinkedIterator() {
current = DoublyLinkedIntSet.this.getFirst();
cursor = 0;
noCursor = false;
}
/**
* Creates a new <code>TRSPTourIterator</code> starting at the given node.
* <p>
* Note that the first call to {@link #next()} of {@link #previous()} will return <code>nodeId</code>
* </p>
*
* @param nodeId
* the id of the current node. If equal to {@link ITRSPTour#UNDEFINED} then the iterator will be
* initialized with the first node
*/
protected DoublyLinkedIterator(int nodeId) {
this(nodeId != UNDEFINED ? nodeId : DoublyLinkedIntSet.this.getFirst(), 0, nodeId != UNDEFINED);
}
/**
* Creates a new <code>TRSPTourIterator</code>.
*
* @param current
* the current
* @param cursor
* the cursor
* @param noCursor
* the no cursor
*/
private DoublyLinkedIterator(int current, int cursor, boolean noCursor) {
super();
this.noCursor = noCursor;
this.current = current;
this.cursor = cursor;
}
/* (non-Javadoc)
* @see java.util.ListIterator#add(java.lang.Object)
*/
@Override
public void add(Integer e) {
DoublyLinkedIntSet.this.insert(e, current);
}
/* (non-Javadoc)
* @see java.util.ListIterator#hasNext()
*/
@Override
public boolean hasNext() {
return current != UNDEFINED;
}
/* (non-Javadoc)
* @see java.util.ListIterator#hasPrevious()
*/
@Override
public boolean hasPrevious() {
return current != UNDEFINED;
}
/* (non-Javadoc)
* @see java.util.ListIterator#next()
*/
@Override
public Integer next() {
if (hasNext()) {
cursor++;
int c = current;
current = DoublyLinkedIntSet.this.getSucc(current);
return c;
} else
throw new NoSuchElementException();
}
/* (non-Javadoc)
* @see java.util.ListIterator#nextIndex()
*/
@Override
public int nextIndex() {
if (noCursor)
throw new IllegalStateException(
"Cannot trust the index position when the iterator was started from an initial node different from the tour start");
return cursor;
}
/* (non-Javadoc)
* @see java.util.ListIterator#previous()
*/
@Override
public Integer previous() {
if (hasPrevious()) {
cursor--;
int c = current;
current = DoublyLinkedIntSet.this.getPred(current);
return c;
} else
throw new NoSuchElementException();
}
/* (non-Javadoc)
* @see java.util.ListIterator#previousIndex()
*/
@Override
public int previousIndex() {
if (noCursor)
throw new IllegalStateException(
"Cannot trust the index position when the iterator was started from an initial node different from the tour start");
return cursor - 1;
}
/* (non-Javadoc)
* @see java.util.ListIterator#remove()
*/
@Override
public void remove() {
DoublyLinkedIntSet.this.remove(getPred(current));
}
/* (non-Javadoc)
* @see java.util.ListIterator#set(java.lang.Object)
*/
@Override
public void set(Integer e) {
DoublyLinkedIntSet.this.set(getPred(current), e);
}
/* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
protected DoublyLinkedIterator clone() {
return new DoublyLinkedIterator(current, cursor, noCursor);
}
/**
* Sub iterator.
*
* @return the doubly linked list iterator
*/
public DoublyLinkedIterator subIterator() {
return clone();
}
}
}