You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

335 lines
8.6 KiB
Java

package com.jwetherell.algorithms.data_structures;
import com.jwetherell.algorithms.data_structures.SkipList.Node;
import com.jwetherell.algorithms.data_structures.interfaces.IMap;
/**
* A set used to store key->values pairs, this is an implementation of an
* associative array.
*
* This implementation is a composition of a Skip List as the backing structure.
*
* http://en.wikipedia.org/wiki/Skip_list
* http://en.wikipedia.org/wiki/Associative_array
*
* @author Justin Wetherell <phishman3579@gmail.com>
*/
@SuppressWarnings("unchecked")
public class SkipListMap<K extends Comparable<K>, V> implements SkipList.INodeCreator<K>, IMap<K,V> {
private SkipList<K> list = null;
public SkipListMap() {
list = new SkipList<K>(this);
}
/**
* {@inheritDoc}
*/
@Override
public V put(K key, V value) {
V prev = null;
SkipList.Node<K> node = list.addValue(key);
if (node instanceof SkipListMapNode) {
SkipListMapNode<K, V> treeMapNode = (SkipListMapNode<K, V>) node;
if (treeMapNode.value!=null) prev = treeMapNode.value;
treeMapNode.value = value;
}
return prev;
}
/**
* {@inheritDoc}
*/
@Override
public V get(K key) {
SkipList.Node<K> node = list.getNode(key);
if (node instanceof SkipListMapNode) {
SkipListMapNode<K, V> mapNode = (SkipListMapNode<K, V>) node;
return mapNode.value;
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(K key) {
return list.contains(key);
}
/**
* {@inheritDoc}
*/
@Override
public V remove(K key) {
Node<K> node = list.removeValue(key);
V value = null;
if (node instanceof SkipListMapNode) {
SkipListMapNode<K, V> treeMapNode = (SkipListMapNode<K, V>) node;
value = treeMapNode.value;
treeMapNode.data = null;
treeMapNode.value = null;
}
return value;
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
list.clear();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return list.size();
}
/**
* {@inheritDoc}
*/
@Override
public boolean validate() {
if (list==null) return true;
java.util.Set<K> keys = new java.util.HashSet<K>();
Node<K> node = list.head;
if (node==null) return true;
if (!validate(node,keys)) return false;
Node<K> next = node.getNext(0);
while (next!=null) {
if (!validate(next, keys)) return false;
next = next.getNext(0);
}
return (keys.size()==size());
}
private boolean validate(Node<K> node, java.util.Set<K> keys) {
if (!(node instanceof SkipListMapNode)) return false;
SkipListMapNode<K,V> tmn = (SkipListMapNode<K,V>)node;
K k = tmn.data;
V v = tmn.value;
if (k==null || v==null) return false;
if (keys.contains(k)) return false;
keys.add(k);
return true;
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Map<K,V> toMap() {
return (new JavaCompatibleTreeMap<K,V>(this));
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (list!=null && list.head!=null) {
Node<K> node = list.head;
while (node!=null) {
if (!(node instanceof SkipListMapNode)) continue;
SkipListMapNode<K,V> sln = (SkipListMapNode<K, V>) node;
builder.append(sln.data).append("=").append(sln.value);
node = node.getNext(0);
if (node!=null) builder.append("\n");
}
}
return builder.toString();
}
/**
* {@inheritDoc}
*/
@Override
public SkipList.Node<K> createNewNode(int level, K key) {
return (new SkipListMapNode<K, V>(level, key));
}
/**
* {@inheritDoc}
*/
@Override
public void swapNode(Node<K> node, Node<K> next) {
K key = node.data;
node.data = next.data;
next.data = key;
if (node instanceof SkipListMapNode && next instanceof SkipListMapNode) {
SkipListMapNode<K,V> node2 = (SkipListMapNode<K,V>) node;
SkipListMapNode<K,V> next2 = (SkipListMapNode<K,V>) next;
V value = node2.value;
node2.value = next2.value;
next2.value = value;
}
}
protected static class SkipListMapNode<K extends Comparable<K>, V> extends SkipList.Node<K> {
protected V value = null;
protected SkipListMapNode(int level, K key) {
super(level, key);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(super.toString());
builder.append("value = ").append(value).append("\n");
return builder.toString();
}
}
private static class JavaCompatibleIteratorWrapper<K extends Comparable<K>,V> implements java.util.Iterator<java.util.Map.Entry<K, V>> {
private SkipListMap<K,V> map = null;
private java.util.Iterator<java.util.Map.Entry<K, V>> iter = null;
private java.util.Map.Entry<K, V> lastEntry = null;
public JavaCompatibleIteratorWrapper(SkipListMap<K,V> map, java.util.Iterator<java.util.Map.Entry<K, V>> iter) {
this.map = map;
this.iter = iter;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNext() {
if (iter==null) return false;
return iter.hasNext();
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Map.Entry<K, V> next() {
if (iter==null) return null;
lastEntry = iter.next();
return lastEntry;
}
/**
* {@inheritDoc}
*/
@Override
public void remove() {
if (iter==null || lastEntry==null) return;
map.remove(lastEntry.getKey());
iter.remove();
}
}
private static class JavaCompatibleMapEntry<K extends Comparable<K>,V> extends java.util.AbstractMap.SimpleEntry<K,V> {
private static final long serialVersionUID = 3282082818647198608L;
public JavaCompatibleMapEntry(K key, V value) {
super(key, value);
}
}
private static class JavaCompatibleTreeMap<K extends Comparable<K>,V> extends java.util.AbstractMap<K,V> {
private SkipListMap<K,V> map = null;
protected JavaCompatibleTreeMap(SkipListMap<K,V> map) {
this.map = map;
}
/**
* {@inheritDoc}
*/
@Override
public V put(K key, V value) {
return map.put(key, value);
}
/**
* {@inheritDoc}
*/
@Override
public V remove(Object key) {
return map.remove((K)key);
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
map.clear();
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsKey(Object key) {
return map.contains((K)key);
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return map.size();
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Set<java.util.Map.Entry<K, V>> entrySet() {
java.util.Set<java.util.Map.Entry<K, V>> set = new java.util.HashSet<java.util.Map.Entry<K, V>>() {
private static final long serialVersionUID = 1L;
/**
* {@inheritDoc}
*/
@Override
public java.util.Iterator<java.util.Map.Entry<K, V>> iterator() {
return (new JavaCompatibleIteratorWrapper<K,V>(map,super.iterator()));
}
};
if (map.list!=null && map.list.head!=null) {
Node<K> n = map.list.head;
while (n!=null) {
if (!(n instanceof SkipListMapNode)) continue;
SkipListMapNode<K,V> node = (SkipListMapNode<K,V>)n;
set.add(new JavaCompatibleMapEntry<K,V>(node.data,node.value));
n = node.getNext(0);
}
}
return set;
}
}
}