package pt.ist.fenixframework.adt.skiplist; import java.io.Serializable; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Random; import pt.ist.fenixframework.dml.runtime.DomainBasedMap; public class SkipList<T extends Serializable> extends SkipList_Base implements DomainBasedMap<T> { private transient final static double probability = 0.25; private transient final static int maxLevel = 32; private transient final static ThreadLocal<Random> random = new ThreadLocal<Random>() { @Override protected Random initialValue() { return new Random(); } }; private transient final static Comparable MIN_VALUE = new TombKey(-1); private transient final static Comparable MAX_VALUE = new TombKey(1); public SkipList() { super(); setLevel(0); SkipListNode<T> head = new SkipListNode<T>(maxLevel, MIN_VALUE, null); SkipListNode<T> tail = new SkipListNode<T>(maxLevel, MAX_VALUE, null); setHead(head); for (int i = 0; i <= maxLevel; i++) { head.setForward(i, tail); } } protected int randomLevel() { int l = 0; while (l < maxLevel && random.get().nextDouble() < probability) l++; return l; } public boolean insert(Comparable toInsert, T value) { boolean result; SkipListNode[] update = new SkipListNode[maxLevel + 1]; SkipListNode node = getHead(); int level = getLevel(); Comparable oid = node.getOid(); for (int i = level; i >= 0; i--) { SkipListNode next = node.getForward(i); while ((oid = next.getKeyValue().key).compareTo(toInsert) < 0) { node = next; next = node.getForward(i); } update[i] = node; } node = node.getForward(0); if (node.getKeyValue().key.compareTo(toInsert) == 0) { result = false; } else { int newLevel = randomLevel(); if (newLevel > level) { for (int i = level + 1; i <= level; i++) update[i] = getHead(); setLevel(level); } node = new SkipListNode<T>(level, toInsert, value); for (int i = 0; i <= level; i++) { node.setForward(i, update[i].getForward(i)); update[i].setForward(i, node); } result = true; } return result; } @Override public T get(Comparable key) { boolean result; SkipListNode node = getHead(); int level = getLevel(); Comparable oid = node.getOid(); for (int i = level; i >= 0; i--) { SkipListNode next = node.getForward(i); while ((oid = next.getKeyValue().key).compareTo(key) < 0) { node = next; next = node.getForward(i); } } node = node.getForward(0); if (node.getKeyValue().key.compareTo(key) == 0) { return (T) node.getKeyValue().value; } else { return null; } } public boolean removeKey(Comparable toRemove) { boolean result; SkipListNode[] update = new SkipListNode[maxLevel + 1]; SkipListNode node = getHead(); int level = getLevel(); Comparable oid = node.getOid(); for (int i = level; i >= 0; i--) { SkipListNode next = node.getForward(i); while ((oid = next.getKeyValue().key).compareTo(toRemove) < 0) { node = next; next = node.getForward(i); } update[i] = node; } node = node.getForward(0); if (node.getKeyValue().key.compareTo(toRemove) != 0) { result = false; } else { for (int i = 0; i <= level; i++) { if (update[i].getForward(i).getOid().compareTo(node.getOid()) == 0) update[i].setForward(i, node.getForward(i)); } while (level > 0 && getHead().getForward(level).getForward(0) == null) { level--; setLevel(level); } result = true; } return result; } public boolean containsKey(Comparable key) { return get(key) != null; } @Override public Iterator<T> iterator() { return new Iterator<T>() { private SkipListNode iter = getHead().getForward(0); // skip head tomb @Override public boolean hasNext() { return iter.getForward(0) != null; } @Override public T next() { if (iter.getForward(0) == null) { throw new NoSuchElementException(); } Object value = iter.getKeyValue().value; iter = iter.getForward(0); return (T) value; } @Override public void remove() { throw new UnsupportedOperationException("This implementation does not allow element removal via the iterator"); } }; } @Override public boolean remove(Comparable key) { return removeKey(key); } @Override public boolean contains(Comparable key) { return containsKey(key); } @Override public int size() { Iterator<T> iter = this.iterator(); int size = 0; while (iter.hasNext()) { size++; iter.next(); } return size; } @Override public void put(Comparable key, T value) { insert(key, value); } @Override public boolean putIfMissing(Comparable key, T value) { return insert(key, value); } }