I've implemented this skip-list yesterday, and I'd like suggestions on how to improve this code, and my coding practices.
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class SkipList<T extends Comparable <T>> {
List<Node<T>> levels;
public SkipList(){
this.levels = new ArrayList<Node<T>>(1);
this.levels.add(new Node<T>());
}
public T search(T value){
Node<T> focus = this.levels.get(levels.size()-1);
if(focus.next != null && focus.next.value.compareTo(value)<0)
focus = focus.next;
while(value != focus.value){
// go as far as you can on this level
while(focus.next != null && value.compareTo(focus.next.value) > 0)
focus = focus.next;
if(value == focus.value) return value;
// if not go down one level
if(focus.down == null) return null;
else focus = focus.down;
}
return null;
}
public void insert(T value){
if(search(value) != null)
return;
// coin flips
Random rand = new Random();
int coinFlip = 0;
while(rand.nextInt(2)==1)
coinFlip++;
// check levels height is not less then coin flip
int before = levels.size();
if(coinFlip >= before){
for(int i=coinFlip ; i >= before ; i--)
levels.add(new Node<T>());
for(int i=levels.size()-1 ; i > 0 ; i--)
levels.get(i).down = levels.get(i-1);
}
// insert to all lower level
Node<T> ins = new Node<T>(value);
Node<T> remember = ins;
for(int i=coinFlip ; i >= 0 ; i--){
// insert to all the levels from coin flip down and remember to set down
insertToLevel(ins,i);
if(i == 0) break;
remember = ins;
ins = new Node<T>(value);
remember.down = ins;
}
}
private void insertToLevel(Node<T> node,int i){
Node<T> focus = levels.get(i);
Node<T> prev = focus;
if(focus.next == null){
focus.next = node;
return;
}
prev = focus;
focus = focus.next;
while( focus.next != null && node.value.compareTo(focus.value) > 0 ) {
prev = focus;
focus = focus.next;
}
if(focus.value == null || focus.value.compareTo(node.value) < 0) focus.next = node;
else{
prev.next = node;
node.next = focus;
}
}
public void delete(T value){
int highestLevelFound = levels.size()-1;
Node<T> focus = this.levels.get(highestLevelFound);
while( !( focus.next != null && focus.next.value.compareTo(value)<=0 ) ){
focus = focus.down;
highestLevelFound--;
}
focus = focus.next;
while(value != focus.value){
// go as far as you can on this level
while(focus.next != null && value.compareTo(focus.value) > 0)
focus = focus.next;
// if it's a hit break, it's on this level
if(value == focus.value) break;
// if not go down one level
if(focus.down == null) return;
else{
focus = focus.down;
highestLevelFound--;
}
}
for(int i=highestLevelFound ; i >= 0 ; i--){
deleteFromLevel(value,i);
}
while(this.levels.get(highestLevelFound).next == null && highestLevelFound>0){
this.levels.remove(highestLevelFound);
highestLevelFound--;
}
}
private void deleteFromLevel(T value,int i) {
Node<T> focus = levels.get(i);
Node<T> prev = focus;
while(value != focus.value){
prev = focus;
focus = focus.next;
}
prev.next = focus.next;
}
}
class Node<T>{
T value;
Node<T> next;
Node<T> down;
public Node(){}
public Node(T value){
this.value = value;
}
}