Welcome to HBH! If you have tried to register and didn't get a verification email, please using the following link to resend the verification email.
SkipList in Java - Java Code Bank
SkipList in Java
This is an example of a more complex data structure - a play on the classic linked list, but maintains pointer references at random level N of max height X for the increasingly sparse and large input sets.
/**
* @author Arabian
*
* Naive base indexed implementation of the SkipList data structure. Ready for Serialization,
* Iteration, and concurrent mapping.
* Amortized logarithmic complexity for search, insertion, deletion, and contains queries.
*
* Original by William Pugh.
*
* @date 4/4/12;
*/
package skipList;
import java.util.Collection;
import java.util.Random;
@SuppressWarnings("unchecked")
public class SkipList<T extends Comparable<? super T>> {
/**
*Static SkipNode constructor. Maintains our data,
*prev pointer, next node pointers, and distance.
*
* @param <T>
*/
private static class SkipNode<T extends Comparable<? super T>> {
private final T data;
private SkipNode<T> prev;
private final SkipNode<T>[] next;
private int[] span;
public SkipNode (T data, int level) {
this.data = data;
next = new SkipNode[level];
span = new int[level];
}
}
/* Global vars */
private SkipNode<T> head;
private SkipNode<T>[] update;
private int[] index;
private int size = 0, level = 1;
private static final double P = 0.5; //Pugh's skiplist cookbook.
private final int MAX_LEVEL;
public final Random random = new Random();
public int t;
/**
* SkipList constructor takes MAX_LEVEL and builds head and necessary
* variables using private build() method;
*
* @param level
*/
public SkipList(int level) {
this.MAX_LEVEL = level;
t = 0;
build(MAX_LEVEL);
}
private void build(int level) {
head = new SkipNode<T>(null, level);
update = new SkipNode[level];
index = new int[level];
for(int i = 0; i < level; i++) {
head.next[i] = head; //set head pointers and distance
head.span[i] = 1;
}
head.prev = head;
}
/**
* Insert method using the standard algorithm. All pointers maintained. and updated,
* along with size.
*
* @param value
* @return true or false if successful or not.
*/
public boolean insert(T value) {
if(value == null)
return false;
final int level_t = randomLevel();
SkipNode<T> x = head;
SkipNode<T> y = head;
int i;
int ind = 0;
for(i = level - 1; i >= 0; i--) {
while(x.next[i] != y && x.next[i].data.compareTo(value) < 0) {
ind += x.span[i];
t++;
x = x.next[i];
}
y = x.next[i];
update[i] = x;
index[i] = ind;
}
if (level_t > level) {
for(i = level; i < level_t; i++) {
head.span[i] = size + 1;
update[i] = head;
}
level = level_t;
}
x = new SkipNode<T>(value, level_t);
for(i = 0; i < level; i++) {
if (i > level_t - 1)
update[i].span[i]++;
else {
x.next[i] = update[i].next[i];
update[i].next[i] = x;
x.span[i] = index[i] + update[i].span[i] - ind;
update[i].span[i] = ind + 1 - index[i];
}
}
x.prev = update[0];
x.next[0].prev = x;
size++;
return true;
}
/**
* insertAll takes java.util.Collection of any object type and inserts.
* using our insert method.
* @param values
*/
public void insertAll(Collection<? extends T> values) {
for(T x : values) {
insert(x);
}
}
/**
* Remove method takes element and redistributes pointers. The actual deletion
* is relegated to our delete() method.
* @param element
* @return true or false
*/
public boolean remove(T element) {
if(element == null)
return false;
SkipNode<T> x = head;
for(int i = level - 1; i >= 0; i--) {
while(x.next[i] != head && x.next[i].data.compareTo(element) < 0)
x = x.next[i];
update[i] = x;
}
x = x.next[0];
if(x == head || x.data.compareTo(element) != 0)
return false;
delete(x, update);
return true;
}
/**
* same as above, but takes index instead of value parameters.
*
* @param index
* @return value at index
*/
public T removeIndex(int index) {
SkipNode<T> x = head;
int ind = 0;
for(int i = level - 1; i >= 0; i--) {
while(ind + x.span[i] <= index) {
ind += x.span[i];
x = x.next[i];
}
update[i] = x;
}
x = x.next[0];
delete(x, update);
return x.data;
}
public void removeAllByValue(Collection<? extends T> values) {
for(T x : values)
remove(x);
}
public void removeAllByIndex(Collection<Integer> values) {
for(Integer x : values)
removeIndex((int) x);
}
/**
* our main deletion method. Takes our updated
* references and redistributes to lazily delete node.
*
* @param node - our current node.
* @param update - updated reference array.
*/
private void delete(SkipNode<T> node, SkipNode<T>[] update) {
for (int i = 0; i < level; i++)
if (update[i].next[i] == node) {
update[i].next[i] = node.next[i];
update[i].span[i] += node.span[i] - 1;
}
else update[i].span[i]--;
node.next[0].prev = node.prev;
while (head.next[level] == head && level > 1)
level--;
size--;
}
/**
* Concurrent random number generator.
*
* @return randomly generated int
*/
protected int randomLevel() {
int x = random.nextInt() | 0x100; //256
x ^= x << 13;
x ^= x >>> 17;
x ^= x << 5;
if ((x & 0x8001) != 0) // test highest and lowest bits
return 1;
int level = 1;
while (((x >>>= 1) & 1) != 0) ++level;
return level+1;
}
/**
* Contains method simply returns boolean using searchBy* methods.
* @param x
* @return true or false
*/
public boolean containsElement(T x) {
return searchByElement(x) != null;
}
/**
* Uses the basic skiplist algorithm to find relevant node.
*
* @param element
* @return SkipNode<T> with relevant value
*/
public SkipNode<T> searchByElement(T element) {
SkipNode<T> curr = head;
for (int i = level - 1; i >= 0; i--)
while (curr.next[i] != head && curr.next[i].data.compareTo(element) < 0)
curr = curr.next[i];
curr = curr.next[0];
if (curr != head && curr.data.equals(element))
return curr;
return null;
}
/**
* Same as above, but greps using given index parameter.
*
* @param index
* @return SkipNode<T> with relevant index.
*/
private SkipNode<T> searchByIndex(int index) {
if(index > size)
return null;
SkipNode<T> curr = head;
int ind = -1;
for (int i = level - 1; i >= 0; i--)
while (ind + curr.span[i] <= index) {
ind += curr.span[i];
curr = curr.next[i];
}
return curr;
}
/**
* Simple index value get method.
* @param index
* @return value at index.
*/
public T get(int index) {
return !(index > size) ? searchByIndex(index).data : null;
}
/* -------------- Utility Methods ------------- */
/**
* Clearing utility method.
*/
public void makeEmpty() {
head = null;
build(MAX_LEVEL);
size = 0;
}
/**
* Checks if empty
* @return true or false;
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Size utility
* @return current size;
*/
public int size() {
return size;
}
/**
* Traversal count
* @return traversal count;
*/
public int traverse() {
return t;
}
}
Comments
Sorry but there are no comments to display