package datastruct;
import java.util.Random;
public class SkipList {
public SkipListEntry head,tail;
public int n;//size
public int h;//high
public Random r;
public SkipList()
{
SkipListEntry p1,p2;
p1 = new SkipListEntry(Integer.MIN_VALUE);
p2 = new SkipListEntry(Integer.MAX_VALUE);
p1.right = p2;
p2.left = p1;
head = p1;
tail = p2;
n = 0;
h = 0;
r = new Random();
}
public Integer get(Integer k)
{
SkipListEntry p = findEntry(k);
return p.value == k ? p.value : null;
}
public void put(Integer k)
{
SkipListEntry p = findEntry(k);
if (p.value == k)
{
//已有了 就不插入了
return;
}
//insert k with random height
SkipListEntry q = new SkipListEntry(k);
q.left = p;
q.right = p.right;
p.right.left = q;
p.right = q;
int i = 0;
while (r.nextDouble() < 0.5)
{
if (i>=h)
{
addLayer();
}
while (p.up == null)
{
p = p.left;
}
p = p.up;
SkipListEntry e = new SkipListEntry(k);
e.left = p;
e.right = p.right;
e.down = q;
p.right.left = e;
p.right = e;
q.up = e;
q = e;
i = i+1;
}
n = n+1;
}
public void remove(Integer k)
{
SkipListEntry p = findEntry(k);
if (p.value != k)
{
return;
}
while (p!=null)
{
p.left.right = p.right;
p.right.left = p.left;
p = p.up;
}
}
public void list()
{
for (int i=1;i<=h;i++)
{
SkipListEntry p = head;
for (int j=1;j<=i;j++)
{
p = p.down;
}
while (p.right!=null && p.right.value!=Integer.MAX_VALUE)
{
p = p.right;
System.out.print(p.value + "->");
}
System.out.println();
}
}
private void addLayer()
{
SkipListEntry p1,p2;
p1 = new SkipListEntry(Integer.MIN_VALUE);
p2 = new SkipListEntry(Integer.MAX_VALUE);
p1.right = p2;
p1.down = head;
p2.left = p1;
p2.down = tail;
head.up = p1;
tail.up = p2;
head = p1;
tail = p2;
h ++;
}
/**
* 查找节点
* @param k 待查找的节点值
* @return 节点,如果没有匹配的值,那么应该是离待插入位置最近的节点,在层1
*/
private SkipListEntry findEntry(Integer k)
{
SkipListEntry p ;
p = head;
while (true)
{
/**
* eg:k = 34
*
* 10 -> 20 ->30 -> 40
* ^
* p is here
*/
while (p.right.value!=Integer.MAX_VALUE && p.right.value <= k)
{
p = p.right;
}
if (p.down!=null)
{
p = p.down;
}
else
{
break;
}
}
return p;
}
/**
* @param args
*/
public static void main(String[] args) {
int COUNT = 100;
SkipList l = new SkipList();
Random r = new Random();
int remove = 0,v;
for (int i=0;i<COUNT/10;i++)
{
v = r.nextInt(COUNT);
if (i == COUNT/10-2)
{
remove = v;
System.out.println("remove:" + remove);
}
l.put(v);
}
l.list();
l.remove(remove);
System.out.println("After:");
l.list();
}
}
class SkipListEntry
{
Integer value;
SkipListEntry up,down,left,right;
public SkipListEntry(Integer value) {
super();
this.value = value;
}
}
参考:http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Map/skip-list-impl.html
相比红黑树:http://stackoverflow.com/questions/256511/skip-list-vs-binary-tree
- Locking skip lists are insanely fast. They scale incredibly well with the number of concurrent accesses. This is what makes skip lists special, other lock based data structures tend to croak under pressure.
- Lock-free skip lists are consistently faster than locking skip lists but only barely.
- transactional skip lists are consistently 2-3 times slower than the locking and non-locking versions.
- locking red-black trees croak under concurrent access. Their performance degrades linearly with each new concurrent user. Of the two known locking red-black tree implementations, one essentially has a global lock during tree rebalancing. The other uses fancy (and complicated) lock escalation but still doesn't significantly out perform the global lock version.
- lock-free red-black trees don't exist (no longer true, see Update).
- transactional red-black trees are comparable with transactional skip-lists. That was very surprising and very promising. Transactional memory, though slower if far easier to write. It can be as easy as quick search and replace on the non-concurrent version.